What's the difference between var and &(*var)

  • A+
Category:Languages

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


&(*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.
  • as Pascal Cuoq commented, var should not be a pointer to void, but the C Standard explicitly allows it for this very case... Shocking indeed.
  • if 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.
  • As commented by Peter, if 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:

  • the size of float is silently assumed to be 4
  • the size of int is silently assumend to be the same 4 bytes
  • c must be a valid pointer, unless ddim is 0
  • ref 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 file
  • end of file and read errors are silently ignored and undefined behavior is possible.

The 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.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: