'array arithmetic - pointer types indexing
In my previous question: Pointer dereference array index I have asked about struct being dereferenced. (I will paste a snippet of code from there for recap):
#include <stdio.h>
#include <stdlib.h>
struct Test { char c; } foo;
int main (void) {
struct Test **ar;
ar=malloc(16);
*ar=malloc(0); //prerequisite for second case (without getting some address from OS, I cannot go 'through' *ar to (*ar+1).
//Does not matter allocation of zero bytes. (only to get some valid address)
*(ar+1) = &foo;
//(**(ar+1)).c='c'; //// first case - works
(*(*ar+1)).c='c'; //// second case - also works, with prerequisite
printf("%c\n", (*(*ar+1)).c); //prints 'c'
return 0;
}
I still do understand between pointer adding +1 in first vs second case. Well I do in the second - adding sizeof(struct Test*) to the address *ar, which like array indexing (so *ar is name pointer of array). But in the first case? what does (**(ar+1)) do? How can I add (what?) some kind of pointer type sizeof(struct Test**) when ar is not array? *(ar+1) dereference address that does not belong to me, but (*ar+1) dereference address of pointer (sizeof(struct Test*)) that DOES belong to me (an array member). So why does the first case work? (from the link, I am trying to give my understanding by resolving type being indexed [ e.g. - in first case a "step/index" is made by sizeof(struct Test**) and in second case by sizeof(struct Test*), but both have same size) - just take a look at the link.
Solution 1:[1]
So why does the first case work?
(**(ar+1)).c='c' doesn't work at all on my specific system.
(**(ar+1)) performs pointer arithmetic on a struct Test ** type, and (*(*ar+1)) performs pointer arithmetic on a struct Test* type.
This means that in the former case, arithmetic is done by sizeof(struct Test *) bytes, in the latter case on sizeof(struct Test) bytes.
The compiler might add padding inside your struct so that it ends up as 4 bytes etc, whatever size a pointer happens to be on your system. So they might end up at the same address by luck. Pointer sizes are commonly 2, 4 or 8 bytes, depending on if a 16, 32 or 64 bit address bus is used.
It is not very meaningful to ponder about what obscure code like this does. Explicit pointer arithmetic in general should be avoided, it is much better practice to use the [] operator to get readable code.
Also please note that malloc(0) gives "either a null pointer
is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object." If you get a null pointer and then attempt arithmetic, you have undefined behavior and anything might happen.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Lundin |
