2

I'm trying to write a function that will access a byte and change it for another. I'm having trouble managing the pointers.

Can someone help me fix this code so that px points to the address, and i can then increment pc (which is the same as px but just as char to avoid incrementing by too many bytes) and then replace what is at mem location pc with something else?

unsigned replace_byte(unsigned x, int i, unsigned char b){
    unsigned int* px = &x; //Takes initial address of first byte.
    unsigned char* pc= (unsigned char*)px; //Recast it too char 
    //pointer to avoid incrementing by too many bytes
    if (i==0) {
       *pc= b; //if i is 0 then replace the byte at mem location pc 
    //with b
    }
    if (i==1) { //if i is 1 or more then inc by that much and replace
        pc = pc+1;
        *pc= b;
    }
    if (i==2) {
       pc=pc+2;
       *pc= b;
    }
    if (i==3) {
        pc=pc+3;
       *pc= b;
    }
    return x;
}

I'm getting return values like this: 305419947 305441656 313218680 2872333944

When i would want to get values like this:

replace_byte(0x12345678, 0xAB, 2) --> 0x12AB5678 replace_byte(0x12345678, 0xab, 0) --> 0x123456AB

Ozzoned
  • 35
  • 6
  • what exactly is not working (except that you should write `return x` instead of `return printf...`)? – Stephan Lechner Sep 07 '17 at 21:07
  • respect our time write the code properly what to hell is this : `return printf("%s\n", ););` – 0___________ Sep 07 '17 at 21:11
  • According to your edit that makes perfect sense, integers are stored with 4 bytes, each bit weighing 1,2,4,8,16,...... Replacing a byte will drastically change the number. If you want the output to look like replace_byte(0x12345678, 0xAB, 2) --> 0x12AB5678, then you will need to write each byte separately. – Jas Sep 07 '17 at 21:24
  • @Jas So if I take the address and then increment, I can access each byte seperately and edit the value at its memory location? Right? Thats what I was trying to do but obviously I've done something wrong.. – Ozzoned Sep 07 '17 at 21:36
  • @Ozzoned Of course you can access each byte separately and edit it as you wish, and the way you are doing it is indeed correct. The bytes _are_ being modified. The problem is that your output is not what you expect it to be right? That is because the computer does not interpret an integer as 4 _separate_ bytes, it interprets them as a **single** large number. Read more on this somewhere, your crazy numbers are correct. The first byte of your integer goes from 0-255, the next one weighs more and goes from 255-32,767. SO if you increment the second byte by ONE, the change will be massive. – Jas Sep 07 '17 at 21:40
  • Explain what you need exactly, like what you are using this for, and we can give you better approaches and ideas. Like **why** do you want to modify a single byte in an integer. – Jas Sep 07 '17 at 21:44
  • The exercise in the textbook states this: _Suppose we number the bytes in a w-bits from 0 (least significant) to w / 8 - 1 (most significant). Write code for the following C function, which will return an unsigned value in which byte i of argument x have been replaced by byte b._ It is taking a hexadecimal number that is 8 numbers long (a.k.a a) "0x12345678" and then replacing one of the bytes "12" "34" "56" or "78" (determined by i) with whatever is passed in as B. – Ozzoned Sep 07 '17 at 21:58
  • Please have a look at my edit, I might have been wrong about the binary stuff, my mistake sorry. If you pass any char in **hexadecimal**, then it does indeed work. Once again sorry for my confusion. – Jas Sep 07 '17 at 22:11
  • Sorry for not making it clearer I was dealing with hexadecimals. Your edit does indeed work correctly now! Just to be clear on line 2, is that where you took the address of x before incrementing it later on? And why for i>3 ? Wouldn't you want to do that for >2 ? I'm real wonky on pointers – Ozzoned Sep 07 '17 at 22:19
  • I did not take the address of x anywhere, I copied x to px. Then I took the address of px on line 3 and assigned it to pc. You could, just like your approach, take the address of x and modify that instead of copying to px. But I prefer to not do this because once you modify a parameter, theres no way to get the original one back; so I usually treat them as constants. – Jas Sep 07 '17 at 22:26
  • I see, that makes sense. You've been amazingly helpful, thank you so much ! – Ozzoned Sep 07 '17 at 22:35

2 Answers2

1

This worked perfectly for me:

#include <stdio.h>

unsigned replace_byte(unsigned x, int i, unsigned char b){
    unsigned int px = x;
    unsigned char* pc= (unsigned char*) &px;
    if (i > 3) return px;
    *(pc + i) = b;
    return px;
}

int main()
{
    int a = 0x12345678;
    a = replace_byte(a, 2, 0x7F); // any hexadecimal character in parameter 3
    printf("%x", a);
}
Jas
  • 808
  • 7
  • 19
  • I believe I do want the address though. My thought process was to take the address of the first byte in memory and then increment from there to access the others. Once I have the address, I can flip back to the value and change the value at that address. – Ozzoned Sep 07 '17 at 21:23
0

This code demonstrate how changing the specific byte of the int type works.

#include <stdio.h>

int main() {
    unsigned int i = 0xffffffff;

    //// make two pointers to the one memory address
    // x - pointer to int. The address will be shifting by 4 bytes, when this
    // pointer will be shifting by 1.
    int *x = &i; 

    // y - pointer to char. The address will be shifting by 1 byte, when this
    // pointer will be shifting by 1.
    char *y = (char *) x;

    //addresses the same here.
    printf("x address = %p\n", x); 
    printf("y address = %p\n", y); 
    puts("");
    //both pointers are shifting by 1, but addresses are different now.
    printf("x + 1 = %p\n", x+1);
    printf("y + 1 = %p\n", y+1);
    puts("");
    //changing the 'i' original value by one byte in turns, one after another.
    printf("i - original:                %x\n", i); 

    *y = 16; 
    printf("i - the first byte changed:  %x\n", i); 

    *(y+1) = 16; 
    printf("i - the second byte changed: %x\n", i); 

    *(y+2) = 16; 
    printf("i - the third byte changed:  %x\n", i); 

    *(y+3) = 16; 
    printf("i - the forth byte changed:  %x\n", i); 

    return 0;
}

Output:

x address = 0x7fffe59e9794
y address = 0x7fffe59e9794

x + 1 = 0x7fffe59e9798
y + 1 = 0x7fffe59e9795

i - original:                ffffffff
i - the first byte changed:  ffffff10
i - the second byte changed: ffff1010
i - the third byte changed:  ff101010
i - the forth byte changed:  10101010
MiniMax
  • 773
  • 2
  • 5
  • 18