1

I'm having trouble reading through a series of * and & operators in order to understand two lies of code within a method. The lines are:

int dummy = 1;
if (*(char*)&dummy) { //Do stuff
}

As best I can determine:

  1. dummy is allocated on the stack and its value is set to 1
  2. &dummy returns the memory location being used by dummy (i.e. where the 1 is)
  3. (char*)&dummy casts &dummy into a pointer to a char, instead of a pointer to an int
  4. *(char*)&dummy dereferences (char*)&dummy, returning whatever char has a numeric value of 1

This seems like an awfully confusing way to say:

if (1){//Do stuuf }

Am I understanding these lines correctly? If so, why would someone do this (other than to confuse me)?

GSerg
  • 76,472
  • 17
  • 159
  • 346
user1245262
  • 6,968
  • 8
  • 50
  • 77
  • 1
    You got it almost right - besides step 4: ( * (char * ) & dummy) is a char –  Jan 03 '14 at 20:33
  • This is a common - and perfectly acceptable - idiom for detecting endianness: [Detecting endianness programmatically](http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program). See also: http://www.codeproject.com/Articles/4804/Basic-concepts-on-Endianness – paulsm4 Jan 03 '14 at 20:58

1 Answers1

1

The code is certainly not portable but is apparently intended to detect the endianess of the system: where the non-zero bit for int(1) is located depends on whether the system is big or little endian. In one case the result of the expression is assumed to be 0, in the other case it is assumed to be non-zero. I think it is undefined behavior anyway, though. Also, in theory there is also DS9k endianess which entirely garbles the bytes up (although I don't think there is any system which actually does it).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • 1
    Why do you think it is undefined behavior? I disagree with that. The code is simply casting a pointer from one type to another and then dereferencing it. I think that your answer is mostly correct except for the part about it being undefined behavior. – shawn1874 Jan 03 '14 at 20:37
  • 1
    @shawn1874: ... and what makes you think that is defined? – Dietmar Kühl Jan 03 '14 at 20:39
  • 1
    OK - I think I understand. char takes 1 byte, int takes more than 1 byte (usually 4). By setting an int equal to 1, 4 bytes of memory are allocated. Each byte is set to zero, except for one of the "end" bytes. If little endian, the first byte is set equal to 1, if big endian, the last byte is set equal to one. The (char*) cast pulls off only the first byte. The 'if' reveals the endianess, by verifying whether or not the first byte is zero. – user1245262 Jan 03 '14 at 20:45
  • What about being more practicable and less nitpicking? –  Jan 03 '14 at 20:47
  • @DieterLücking: I'm not sure what you mean? I described what it is probably meant to do and just also stated that it may not do what it is meant to do. What's wrong with mentioning that the approach could be flawed? – Dietmar Kühl Jan 03 '14 at 20:55
  • @DietmarKühl: There's nothing "nitpicking" about making others aware of type-punning rules. In general you can't just cast one pointer to a totally different pointer and say "hey, this is fine, stop nitpicking" – Lightness Races in Orbit Jan 03 '14 at 21:51
  • 3
    @DietmarKühl: The C spec says that it always possible to convert a pointer to any object to a char pointer and access the bytes of the object individually. The actual values you will get are implementation defined, but the behavior IS defined -- it is not undefined, so will not crash or otherwise corrupt things. – Chris Dodd Jan 03 '14 at 22:49
  • 3
    @LightnessRacesinOrbit: while you can't cast to *any* pointer type, you can always cast to a char pointer type and access the individual bytes. char pointers are special that way. – Chris Dodd Jan 03 '14 at 22:50