Reputation: 83
Some source code use the notation &(*var)
where var
is already a pointer, like int *var = ...
.
Is there a difference between this two notations ?
Is var != &(*var)
?
Example: https://github.com/FreeFem/FreeFem-sources/blob/develop/src/medit/inout_popenbinaire.c#L40
Upvotes: 8
Views: 1913
Reputation: 144951
&(*var)
evaluates to the same as var
in most circumstances, at compile time, but note some caveats:
var
should be a valid pointer, although there is not reason for the compiler to generate code to dereference it. Indeed C11 specifies that there is no undefined behavior for &*var
even if var
is a null pointer.var
should not be a pointer to void
, but the C Standard explicitly allows it for this very case... Shocking indeed.var
is an array, with more than one element, var
and &*var
have a different type and sizeof(var)
and sizeof(&(*var))
have a different value: the first is the size of the array while the second is the size of a pointer to the its first element.var
is an uninitialised pointer, then evaluating var == &(*var)
gives undefined behaviour (since evaluating either side of the ==
gives undefined behaviour - accessing the value of an uninitialised variable is what gives the undefined behaviour).The example you link to in the question uses this construction for no purpose whatsoever:
#define WrdSiz 4
void getline_bin_float_vertex(int ddim, double *c, int *ref) {
int i;
float ff;
for (i = 0; i < ddim; i++) {
fread((unsigned char *)&(ff), WrdSiz, 1, stdin);
c[i] = ff;
}
fread((unsigned char *)&(*ref), WrdSiz, 1, stdin);
}
The programmer is reading a number of floating point values and an integer from a file redirected into the standard input. The code is awkward and non-portable:
float
is silently assumed to be 4int
is silently assumend to be the same 4 bytesc
must be a valid pointer, unless ddim
is 0ref
must be a valid pointer as fread
will try and store 4 bytes at the address it points to, unless the stream is at end of fileThe code can be simplified and protected this way:
#define WrdSiz 4
/* read values from stdin, return non-zero in case of failure */
int getline_bin_float_vertex(int ddim, double *c, int *ref) {
int i;
float ff;
assert(sizeof float == WrdSiz);
assert(sizeof int == WrdSiz);
assert(dim == 0 || c != NULL);
assert(ref != NULL);
for (i = 0; i < ddim; i++) {
if (fread(&ff, sizeof ff, 1, stdin) != 1)
return -1;
c[i] = ff;
}
if (fread(ref, sizeof(*ref), 1, stdin) != 1)
return -1;
return 0;
}
Other portions of this source code show poor or even invalid constructions, you should study this package only for examples of what not to do.
Upvotes: 10
Reputation: 67749
Probably it was a longer expression inside the parentheses but during the debugging has been reduced to this one and left in the source code . It does not make any sense
Edit - the github example it looks exactly as I expected.
Upvotes: 0
Reputation: 1
&(*var)
might have had undefined behavior when var
(a pointer variable) does not contain a valid address for old versions of C. Be scared in that case. But C11 standard §6.5.3.2 states that the compiler has to handle it as equivalent in all cases (including when var
is NULL
)
So var == &(*var)
is true when var
contains a valid address. When it contains something else (e.g. NULL
), it might crash (segmentation fault) if you use a non-C11 conforming non-optimizing compiler (but most compilers, even old ones, won't generate some crashing code in that case)
But the compiler (even an old C99 one) is allowed (under as-if rule) to optimize &(*var)
into var
Upvotes: 5