-3

Structure pointer returning the start byte of member of structure .I wondered how it works. PLease some one help me to get know about this.

 #include <stdio.h>

 typedef struct node {
  char mem;
  double mem2;
  char mem3;
  int mem4;
  char mem5;
  char mem6;
 }NODE;
 int main()
 {
     NODE * m;
     printf("%u",&m->mem3);
     return 0;
 }

Output is 16

AADHI A.R
  • 35
  • 6
  • 2
    You are not allocating memory for `NODE *m`. You are invoking undefined behavior. – Micha Wiedenmann Nov 20 '18 at 09:55
  • Can you elaborate on your problem? – Sourav Ghosh Nov 20 '18 at 09:56
  • More or less the *exact* same question [as this one](https://stackoverflow.com/q/53387230/440558). Please tell the rest of your class to not post duplicates. – Some programmer dude Nov 20 '18 at 09:58
  • Also, change the print to `printf("%c", m->mem3);`. Note how you don't need the `&`, you're already dereferencing with the `->` operator. – Blaze Nov 20 '18 at 09:59
  • Its is returning the starting byte of structure member here.(i.e) mem-0, mem2-8 , mem3 -16, mem4 -20 ,mem5-24 , mem6 - 25. How it returning the starting byte number. @ Micha Wiedenmann @ Sourav Ghosh @Blaze – AADHI A.R Nov 20 '18 at 10:03
  • Like I said in the other question, uninitialized local variables (like `m`) will have an *indeterminate* (and seemingly random) value. Dereferencing such a pointer leads to [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior). As does using the incorrect `printf` format, the correct format to print a `void *` pointer (and yes you *must* cast to that type) is `"%p"`. And if you have undefined behavior, there's no speculating about behavior. – Some programmer dude Nov 20 '18 at 10:07
  • @Some programmer dude It is not crashing . Instead of that it giving the 16 which is the starting byte of mem3 in structure . Please explain this – AADHI A.R Nov 20 '18 at 10:11
  • ***Undefined behavior!*** Sometimes it might seem to work. Sometimes it might give wrong results. Sometimes it might cause crashes. And sometimes it might summon [nasal demons](http://www.catb.org/jargon/html/N/nasal-demons.html). – Some programmer dude Nov 20 '18 at 10:29
  • As for this ***specific*** case, it seems you're "lucky" and that `m` just happens to be zero, which is on most platform the null pointer. That means when you take the address of a member, it will just so happen to be equal to the offset of the member inside the structure. However, never ever rely on undefined behavior. What you do is *wrong*, plain and simple. – Some programmer dude Nov 20 '18 at 10:36
  • @nasal demons I tried in 3 compilers and it gave same result. – AADHI A.R Nov 20 '18 at 10:36
  • Your edit significantly changed the question. Please avoid changes that make most answers and comments invalid. No one wants to aim at a moving target. – Gerhardh Nov 20 '18 at 11:19
  • Printing 16 results from application of the famous "garbage in garbage out" pattern. – Gerhardh Nov 20 '18 at 11:20
  • That is no longer a valid duplicate. – Gerhardh Nov 20 '18 at 11:21
  • @Gerhardh It is not random number nor Garbage value . mem is 0 and its starting byte is 0. mem2 is double data type so it starts from 8th byte and it left previous 7 bytes and mem3 is char data type,so it starts after mem3 that is 16th byte and its immediate next is int so mem4 starts from 20th byte .like wise its going. I want to know what is this behavior ? – AADHI A.R Nov 20 '18 at 11:57
  • You do not initialize the pointer variable. Therefore you can get any address. (Garbage in). There you could get 0xCDCDCDCD, 0xDEADBEAF or any other value. Just by accident you seem to get a `NULL` pointer. Then you add 16 bytes for the offset of `mem3` and print the resulting address. This is +16. (garbage out). For your `NULL` pointer the offset of the member is at address 16. – Gerhardh Nov 20 '18 at 12:01
  • @Gerhardh Then what about mem,mem2,mem4,mem5 and mem6. It also giving correct output in many compilers as I like mentioned above. mem-1,mem2-8,mem3-16,mem4-20,mem5=24 and mem6-25 – AADHI A.R Nov 20 '18 at 12:05
  • What about them? It will always print the offset within the structure as long as you feed in a `NULL` poiner. What do you mean with "correct output"? Adding the offset to an unspecified address is undefined behaviour. It can print "correct" output. Or not. – Gerhardh Nov 20 '18 at 12:08
  • Is your question why it prints the offset or is your question why the offsets are what they are? – Gerhardh Nov 20 '18 at 12:09
  • @Gerhardh If it is a garbage value then how it will give the same pattern of output in all compilers and if I Change the data type of one member the output will be according to that. Suppose if I change mem2 datatype to char. Then mem - 0 and mem2-1 and mem3-2 and mem4-4 and so on. – AADHI A.R Nov 20 '18 at 12:10
  • Again: It only depends on the value of your pointer. Any variable with non-static duration is not defined to have any specific value. Because some compilers or libaries initialize the stack with 0 before running your program. Others don't do this. That does not make an unspecified value anything useful. And a few compilers behaving similar does not make it guaranteed. – Gerhardh Nov 20 '18 at 12:14
  • @Gerhardh int a = (int)&((NODE *)0)->mem3; It also gives output as 2. Could you please explain this statement. – AADHI A.R Nov 20 '18 at 12:18
  • Ah. Finally. Your question is Why are the offsets what they are? With `mem2` being a `char` the first 3 members are simply stored in consecutive memory locations. (`mem3` is stored at offset 2) With `mem2` being double, some padding is added. For a `double` the offset (with that architecture) is padded to multipes of eight. And the size is also 8 bytes. This make `mem3` being located at offset 16. You might want to search for "padding" – Gerhardh Nov 20 '18 at 12:24
  • @Gerhardh I want to know how that statement returns offset instead of address. – AADHI A.R Nov 20 '18 at 12:26
  • If you put a struct at address `NULL` and add an offset for your members, What would you expect other than `0 + ` which is ``? The offset is the address. – Gerhardh Nov 20 '18 at 12:46
  • @Gerhardh thanks .I got it. Now I feel some what ok . It struck my mind from morning – AADHI A.R Nov 20 '18 at 12:50

1 Answers1

0

The program actually should crash because pointer m is not pointing valid memory location. Below code can give the result.

NODE M;
NODE *ptr = &m;
Printf(“%x”, &ptr->mem3);

%x will give hexadecimal address value.

anand
  • 163
  • 7