tags:

views:

135

answers:

4

Hi! I'm reading MAC addresses (in standard hex notation, e.g. 00:11:22:33:44:55) from stdin and converting them into a 6 byte variable hw_addr as decimals:

u8 hw_addr[6];

scanf("%2x:%2x:%2x:%2x:%2x:%2x", &hw_addr[0], &hw_addr[1], &hw_addr[2], &hw_addr[3], &hw_addr[4], &hw_addr[5]);

The only problem is that I'm getting 6 scanf warnings:

warning: format '%2x' expects type 'unsigned int *', but argument 3 has type 'u8 *'

.....

Any way to get rid of these warnings without wasting an int for each field?

+4  A: 

Just use the right type

So you are using a machine that has billions of bytes of RAM and you want to save 6 of them?

If you are keeping an array of millions of mac addresses you should convert them to a packed format after reading them. But no harm is done by supplying canonical ints to scanf().

For that matter, if hw_addr[] is a local variable, then it effectively uses no space at all as it will be reused for other locals after your function returns.

Since you can't optimize everything, it is important to focus your optimization effort on things that really matter.

DigitalRoss
Maybe he isn't trying to optimize anything. Maybe it's just easier to have the I/O function return what you want, than introducing a local to cast.
Potatoswatter
I'm not the only one who read that as concern for saving memory. And he did say "wasting an int". But regardless of intent, scanf() has a particular interface which must be used, and no harm will come from using it.
DigitalRoss
+1  A: 

you are reading unsigned int into char address, this may not be very portable or safe. just use int array as a buffer to read and then copy to byte array

aaa
@Matthew big endian machines will overwrite previously scanned bytes. Last byte will always overrun, regardless of architecture. Int helps because then you are reading n bytes into n bytes rather than one byte
aaa
+3  A: 

According to my scanf manpage,

 hh       Indicates that the conversion will be one of dioux or n
          and the next pointer is a pointer to a char (rather than
          int).

So you want "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"

Potatoswatter
do you have a link to the page? I'm not seeing this at http://www.cplusplus.com/reference/clibrary/cstdio/sscanf/
John Knoeller
http://www.opengroup.org/onlinepubs/000095399/functions/fscanf.html
Matthew Flaschen
@John: See C99 spec sections 7.19.6.1.7 and 7.19.6.3.2
dreamlax
dreamlax: So this is C99 only? that would explain it.
John Knoeller
@John: Yeah looks like it.
dreamlax
@John: Matthew's link is to the POSIX:2004 spec; I don't know if POSIX '04 includes all of C99, but when it comes to pure library functions like `scanf`, I think OS compatibility is probably an independent cause for library support.
Potatoswatter
+2  A: 

The warnings are an indication of a serious issue. You are passing pointers to unsigned bytes but the scanf function is going to be writing 32bits to those pointers. For the first 3 values, the extra 24 bits will overwrite parts of the hw_addr array, but for the last 3 values, you are overwriting some other variable on the stack.

To avoid a bad crash, at the very least you need to overallocate hw_addr

u8 hw_addr[6+3];

Will at least prevent your code from trashing the stack. But really, you should just be using the correctly sized values for scanf, and converting from ints back to unsigned bytes afterwards.

John Knoeller