1

Possible Duplicate:
Converting an int into a 4 byte char array (C)

Using the Dynamic C program (the language is C), I am trying to convert an int into an array of bytes 4 places long. So far I have looked online and I have found a few examples. However, none seem to work for me. I have had an ongoing problem where the correct byte numbers are printed, but they are repeated twice for some reason. I have provided the code below:

void main(){
 int a=1379;
 int i=0;
 unsigned char value [4];

value[3] = (byte) (a & (0xFF));
value[2] = (byte) ((a >> 8) & 0xFF);
value[1] = (byte) ((a >> 16) & 0xFF);
value[0] = (byte) ((a >> 24) & 0xFF);
//convert int values to bytes by placing them in a char buffer

for(i=0;i<4;i++){
 printf("%d",value[i]);
 printf(", ");
 }
printf("\n");
}

For example, with this value the program prints "5, 99, 5, 99," when it should print "0, 0, 5, 99". Thank you for your help.

Community
  • 1
  • 1
user1506919
  • 2,377
  • 5
  • 20
  • 15
  • There's something you're not telling us. – Hot Licks Jul 11 '12 at 19:11
  • 1
    I'm thinking it's a language (for microcontrollers) that has 16-bit ints. – Hot Licks Jul 11 '12 at 19:13
  • You should initialise your array, `unsigned char value[4] = {0};`. – Daniel Fischer Jul 11 '12 at 19:14
  • Builds and runs fine here, with the expected result. Changed the byte casts to char though, since there's no byte in linux gcc. – inVader Jul 11 '12 at 19:14
  • 1
    @pstrjds -- Just because the title's the same does not make it a dupe. – Hot Licks Jul 11 '12 at 19:17
  • What do you get when you write `printf("%d\n", sizeof(int));`? Have you tried using `uint32_t` instead of `int`? – Adam Rosenfield Jul 11 '12 at 19:17
  • 5
    1) main should return int 2) remove the (byte) casts (what is byte?) they can only do harm. 3) shifting signed ints will sign-extend them, use preferrably unsigned entities to shift. 4) use %u printf format to print unsigned types. 5) you are assuming 32 bits ints, and CHAR_BIT=8. 6) sizeof is your friend. – wildplasser Jul 11 '12 at 19:17
  • `byte` is not a standard C type – m0skit0 Jul 11 '12 at 19:18
  • @HotLicks - Not basing off of title, basing off of what is being done, that other question covers this same ground, converting an int into a char array. – pstrjds Jul 11 '12 at 19:18
  • @pstrjds -- But the other question doesn't answer this one. – Hot Licks Jul 11 '12 at 19:19
  • 'You should initialise your array' -- no, it's pointless and useless to do that. – Jim Balter Jul 11 '12 at 19:40
  • @wildplasser: Actually `"%u"` is specifically for `unsigned int`. On most implementations, `unsigned char` promotes to `int`, so `"%d"` is correct. For 100% portability, cast to `unsigned int` and use `"%u"` -- or use `"%hhu"` (added in C99). – Keith Thompson Jul 11 '12 at 21:08
  • You're assuming that `int` is 4 bytes. You should at least document that assumption. – Keith Thompson Jul 11 '12 at 21:09
  • @KeithThompson. Thanks. Yes, I know about the default promotions, but I tend to be careful with vararg functions. My answer below casts to (unsigned int), which still is not necessary. – wildplasser Jul 11 '12 at 21:12
  • @wildplasser: In fact, it is necessary, or at least a good idea. As I said, `char` promotes to `int` (except on exotic systems where plain `char` is unsigned and `CHAR_MAX > INT_MAX`). Passing an `int` argument for a `"%u"` format is ok in certain circumstances (due to a special-case guarantee about the relationship between `int` and `unsigned int`, though some readings of the literal wording of the standard say it's not safe), but I consider it poor style. – Keith Thompson Jul 11 '12 at 21:15
  • BTW the char array in the OP was explicitely unsigned. – wildplasser Jul 11 '12 at 21:17

3 Answers3

4

It's almost certainly the case that "Dynamic C" is an implementation with an int of 16 bits, which is perfectly "legal" for C. If the int is 16 bits, any shift over 16 bits is modulo-16, so the second two shifts duplicate the first two.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • +1 since this is either the answer OR it is a duplicate question :) – pstrjds Jul 11 '12 at 19:24
  • For further info, based on this page [http://www.rabbitsemiconductor.com.cn/products/dc/index.shtml](http://www.rabbitsemiconductor.com.cn/products/dc/index.shtml) mentioning dynamic c 32, I would guess that dynamic c has 16 bit `int` – pstrjds Jul 11 '12 at 19:26
  • 1
    @pstrjds It's not a duplicate question at all. The other question doesn't mention the behavior this one does, behavior that indicates a 16-bit machine. – Jim Balter Jul 11 '12 at 19:44
  • @JimBalter - I added the smily face to point out that I was making a poor joke. I realized after reading further it was not a duplicate and was responding to Hot Licks that I had realized that and upvoted his correct answer. – pstrjds Jul 11 '12 at 20:15
  • I believe its actually UB to shift by more than the length of the variable, may be worth saying this. The compiler probably just happens to do something sensible. – Vality Mar 02 '15 at 14:48
  • @Vality - Well, it *used* to be that the shift was *defined* to be modulo the word length, but I can't guess how the standard might have changed since I last helped create a C compiler about 15 years ago. (I remember because it was a minor PITA to implement this, since the "natural" thing would be to just shift away the significance.) – Hot Licks Mar 02 '15 at 19:28
1

You need to copy the bits from your int variable into the char-array. You can simply do that with memcpy like this:

#include <stdio.h>
#include <string.h>

void split(int val, unsigned char *arr) {
    memcpy(arr, &val, sizeof(int));
}

int main() {
    unsigned char bytes[4];
    split(1379, bytes);
    printf("%d, %d, %d, %d\n", bytes[0], bytes[1], bytes[2], bytes[3]);
}
qwertz
  • 14,614
  • 10
  • 34
  • 46
0
#include <stdio.h>
#include <string.h>

int main(void){
 int a=1379;
 unsigned bot,top ;
 unsigned char value [sizeof a];

 memcpy (value, &a, sizeof value);

 /* You can omit this loop if you are on a big-endian machine */
#if LITTLE_ENDIAN
 for (bot =0, top = sizeof value; --top > bot; bot++) {
    unsigned char tmp;
    tmp = value[bot];
    value [bot] = value[top];
    value[top] = tmp;
    }
#endif

for(bot=0;bot < sizeof value;bot++){
 printf("%u", (unsigned int) value[bot]);
 printf(", ");
 }
printf("\n");
return 0;
}
wildplasser
  • 43,142
  • 8
  • 66
  • 109
  • The code makes no assumptions about the sizes of ints or characters; that's why there are no manifest constants left in it. (and gcc unrolls the "silly" loop, anyway) – wildplasser Jul 11 '12 at 19:49