B
Beej Jorgensen
Here's what I'm trying to do: portably serialize signed 16-bit integers.
I'd like some ideas for improvement here.
1 void pack16(unsigned char buf[2], int16_t v)
2 {
3 uint16_t v2 = v;
4 buf[0] = v2 >> 8;
5 buf[1] = v2;
6 }
7 int16_t unpack16(unsigned char buf[2])
8 {
9 uint16_t v2 = buf[0] << 8 | buf[1];
10
11 if (v2 > 0x7fffu) { // check for negative number
12 return -(0xffffu - v2 + 1u);
13 }
14
15 return v2;
16 }
Comments/Questions:
1. I believe the direct assignment to the unsigned variable in pack16()
line 3 should give us the two's complement negative by C99-6.3.1.3p2.
2. By the same paragraph, I think "&0xff"s on lines 4 and 5 are
unnecessary.
3. Are casts required on line 12 for any of the constants? I'm thinking
the answer is "no" by C99-6.4.4.1p5.
4. Are casts required on the return values? Or anywhere on the
expression on line 12? I'm thinking no, but can't find a passage to
cite.
5. In unpack16(), I cannot portably assign the (buf[0]<<8)|buf[1]) into an
int16_t as it might overflow (C99-6.3.1.3p3.) And in pack16(), I
cannot portably assign v>>8 into buf[0] if v is negative
(C99-6.3.1.3p4.)
6. In the code, I assume the implementation supports int16_t and
uint16_t, which it is not required to do. But I don't see why the
above code shouldn't work with the "least16" variants.
7. Endianess issues? sizeof-related issues? sizeof-related issues if
least16-type variables were used? CHAR_BIT-related issues? Integer
promotion-related issues?
8. Any way to take advantage of the fact that int16_t is two's
complement in unpack16()?
Anything else? Something feels wrong or oversimplified or
overcomplicated or lame.
-Beej
I'd like some ideas for improvement here.
1 void pack16(unsigned char buf[2], int16_t v)
2 {
3 uint16_t v2 = v;
4 buf[0] = v2 >> 8;
5 buf[1] = v2;
6 }
7 int16_t unpack16(unsigned char buf[2])
8 {
9 uint16_t v2 = buf[0] << 8 | buf[1];
10
11 if (v2 > 0x7fffu) { // check for negative number
12 return -(0xffffu - v2 + 1u);
13 }
14
15 return v2;
16 }
Comments/Questions:
1. I believe the direct assignment to the unsigned variable in pack16()
line 3 should give us the two's complement negative by C99-6.3.1.3p2.
2. By the same paragraph, I think "&0xff"s on lines 4 and 5 are
unnecessary.
3. Are casts required on line 12 for any of the constants? I'm thinking
the answer is "no" by C99-6.4.4.1p5.
4. Are casts required on the return values? Or anywhere on the
expression on line 12? I'm thinking no, but can't find a passage to
cite.
5. In unpack16(), I cannot portably assign the (buf[0]<<8)|buf[1]) into an
int16_t as it might overflow (C99-6.3.1.3p3.) And in pack16(), I
cannot portably assign v>>8 into buf[0] if v is negative
(C99-6.3.1.3p4.)
6. In the code, I assume the implementation supports int16_t and
uint16_t, which it is not required to do. But I don't see why the
above code shouldn't work with the "least16" variants.
7. Endianess issues? sizeof-related issues? sizeof-related issues if
least16-type variables were used? CHAR_BIT-related issues? Integer
promotion-related issues?
8. Any way to take advantage of the fact that int16_t is two's
complement in unpack16()?
Anything else? Something feels wrong or oversimplified or
overcomplicated or lame.
-Beej