2

I was wondering if I could use a char* value to access to each byte of an int value... So I tried to use a pointer value to access the first byte of the int and a for cycle to access the other bytes of int...
Here's the code:

int char_to_bin(char* d){
    int p= (int)*d;
    int i=0,number=0;
    if (p>=0){
        do{

            number+= (p%2)*(pow(10,i));
            i++;
            p= p/2;
            }while (p>0);
        }
    else{
        p=p *(-1);
        do{

            number+= (p%2)*pow(10,i);
            i++;
            p=p/2;
            }while (p>0);
        number*=-1;
        }

    return number;
}

long int int_to_bin(int* p){
    long int j=1,number=0,number1=0,number2=0,digits;
    char* c=&p;
    number=char_to_bin(c);
    for (j;j<(sizeof(int)/sizeof(char));j++){
        number1=char_to_bin(c+j);
        digits=floor(log10(abs(number1))) + 1;
        number2=number1*pow(10,digits);
        number=number1+number2;
    }
    return number;
}


int main(){

    char k= 100;
    char* j= &k;
    int inte=100;
    int *h;
    h= &inte;
    int c= char_to_bin(j);
    printf("%d\n",c);
    long int d= int_to_bin(h);
    printf("%ld\n",d);
}

the function int char_to_bin(char* d) converts a pointed char value to a binary number, and all the tests I've done on it show it works. But as I use int char_to_bin(char* d) in int_to_bin(int* p) something goes wrong.
Basically, int_to_bin(int* p) should convert the first byte of the pointed int in binary, and then convert the following bytes (since char* points at one only byte) to decimal, multiply the bytes for 10^(number of digits), so that I might get a number like "000000001100100" for example but something goes wrong and the result of the function is far different from binary, plus, i have tried to put a printf("%d \n",number1) in the int_to_bin(int* p) function, like this:

long int int_to_bin(int* p){
    long int j=1,number=0,number1=0,number2=0,digits;
    char* c=&p;
    number=char_to_bin(c);
    for (j;j<(sizeof(int)/sizeof(char));j++){
        number1=char_to_bin(c+j);
        printf("%d \n",number1); //---------------here------------------
        digits=floor(log10(abs(number1))) + 1;
        number2=number1*pow(10,digits);
        number=number1+number2;
    }
    return number;
}

to check the value contained in the given memory address... As far as I know, int variable types occupy 4 bytes of memory, and the sum of the content of the bytes is the value or the variable... But I get results that summed are totally different from the variable value.
Is there anything to be done to fix this, or should I just give up and try to convert the int passed int_to_bin(int* p) into char and pass it to the char_to_bin(char* p) function?

Pldx
  • 87
  • 1
  • 3
  • 6
  • 2
    Probably the 'int' you're talking about is an 'unsigned int' or 'uint32'. Also, you probably ought to do this by masking the 'uint32' by doing something like 'unsigned char hi_byte = myUint32 & 0xFF00' and 'unsigned char lo_byte = myUint32 & 0x00FF'. – John Jesus Jun 03 '14 at 15:31

1 Answers1

5

As far as I know, int variable types occupy 4 bytes of memory, and the sum of the content of the bytes is the value or the variable...

Well, int is sizeof(int) bytes, which is usually 4 on modern PC operating systems (both 64 and 32 bit), but it can be anything as long as sizeof(short) <= sizeof(int) <= sizeof(long). So always use sizeof instead of hard-coded value.

But value is not sum of contents... That would be very wasteful, same bytes in different order would give same int. Value is, depending on byte order, and assuming unsigned numbers:

(c[0] << 24) | (c[1] << 16) | (c[2] << 8) | (c[3] << 0); // big endian

or

(c[3] << 24) | (c[2] << 16) | (c[1] << 8) | (c[0] << 0); // little endian

where unsigned char *c = (unsigned char*)(&unsigned_int_variable);.


Note that even though char* pointers are exception (see comments), generally setting pointers of different types to point to values breaks so called "strict aliasing rules", which you should read about before doing this kind of thing.

Community
  • 1
  • 1
hyde
  • 60,639
  • 21
  • 115
  • 176
  • 2
    `char *` is an exception to the strict aliasing rule (to allow things like `memcpy` to be implemented). But otherwise this is correct. – Tavian Barnes Jun 03 '14 at 15:48
  • @TavianBarnes Updated answer about `char*` aliasing, but related to that, `memcpy` takes `void*` so what does `char*` have to do with it? – hyde Jun 03 '14 at 16:02
  • `memcpy` could be implemented internally by casting the pointers to `char *` and copying `char`s. Types other than `char` there would violate strict aliasing. – Tavian Barnes Jun 03 '14 at 16:12
  • @TavianBarnes I updated the answer a bit about strict aliasing, can you give a 2nd opinion about it being correct? – hyde Jun 05 '14 at 08:27
  • You're correct about the char rule being "one way", but from my reading of the standard it doesn't apply here. If you had a `char` array and you accessed it through an `int*` then there would be a problem though. – Tavian Barnes Jun 05 '14 at 12:57
  • @TavianBarnes Mmmyep, rolled back after actual testing (gcc -O2)... `char*` seems to be safe both ways and worked correctly, while other pointer types aliased produced wrong output, and so did `char*` when using `restrict` keyword. – hyde Jun 05 '14 at 14:40