问题
For a course about the functioning of operating systems, we had to write a malloc/free implementation for a specific sized struct. Our idea was to store the overhead, like the start and end of the specified (static) memory block our code has to work in, in the first few addresses of that block.
However, something went wrong with the calculation of the last memory slot; We're adding the size of all usable memory slots to the address of the first usable memory slot, to determine what the last slot is. However, when adding the int sizeofslots to the address of currentslot, it actually adds sizeofslots 4 times to this address. Here's the relevant code:
/* Example memory block*/
/* |------------------------------------------------------------------------------|*/
/* | ovr | 1 t | 0 | 1 t | 1 t | 1 t | 0 | 0 | 0 | 0 | 0 | 0 | 0 |*/
/* |------------------------------------------------------------------------------|*/
/* ovr: overhead, the variables `currentslot`, `firstslot` and `lastslot`.
* 1/0: Whether or not the slot is taken.
* t: the struct
*/
/* Store the pointer to the last allocated slot at the first address */
currentslot = get_MEM_BLOCK_START();
*currentslot = currentslot + 3*sizeof(void *);
/* The first usable memory slot after the overhead */
firstslot = currentslot + sizeof(void *);
*firstslot = currentslot + 3*sizeof(void *);
/* The total size of all the effective memory slots */
int sizeofslots = SLOT_SIZE * numslots;
/* The last usable slot in our memory block */
lastslot = currentslot + 2*sizeof(void*);
*lastslot = firstslot + sizeofslots;
printf("%p + %i = %p, became %p\n", previous, sizeofslots, previous + (SLOT_SIZE*numslots), *lastslot);
We figured it had something to do with integers being 4 bytes, but we still don't get what is happening here; Can anyone explain it?
回答1:
When you add an integer to a pointer, it increments by that many strides (i.e. myPointer + x will increment by x*sizeof(x). If this didn't happen, it would be possible to have unaligned integers, which is many processor architectures is a fault and will cause some funky behaviour, to say the least.
Take the following as an example
char* foo = (char*)0x0; // Foo = 0
foo += 5; // foo = 5
short* bar = (short*)0x0; // Bar = 0; (we assume two byte shorts)
bar += 5; // Bar = 0xA (10)
int* foobar = (int*)0x0; // foobar = 0; (we assume four byte ints)
foobar += 2; // foobar = 8;
char (*myArr)[8]; // A pointer to an array of chars, 8 size
myArr += 2; // myArr = 0x10 (16). This is because sizeof(char[8]) = 8;
回答2:
C's pointer arithmetic always works like this; addition and subtraction is always in terms of the item being pointed at, not in bytes.
Compare it to array indexing: as you might know, the expression a[i] is equivalent to *(a + i), for any pointer a and integer i. Thus, it must be the case that the addition happens in terms of the size of each element of a.
To work around it, cast the structure pointer down to (char *) before the add.
回答3:
Example
const int MAX = 3;
int main ()
{
int var[] = {10, 100, 200};
int i, *ptr;
/* let us have array address in pointer */
ptr = var;
for ( i = 0; i < MAX; i++)
{
printf("Address of var[%d] = %x\n", i, ptr );
printf("Value of var[%d] = %d\n", i, *ptr );
/* move to the next location */
ptr++;
}
return 0;
}
Output::
Address of var[0] = bfb7fe3c
Value of var[0] = 10
Address of var[1] = bfb7fe40
Value of var[1] = 100
Address of var[2] = bfb7fe44
Value of var[2] = 200
You can deduce from the example that, a pointer increments itself by "Number Of Bytes" = "Size of the type it is pointing to". Here it is, Number Of bytes = sizeof(int). Similarly, it will increment itself 1 byte in case of char.
来源:https://stackoverflow.com/questions/20397360/adding-int-to-address-causes-int-to-be-added-4-times