Structure member offset.

G

gokrix

#include <stdio.h>
#include <stdlib.h>

struct s
{
int i;
char c;
float f;
};

int main()
{
printf("addr is [%p]. \n", &(((struct s*)0)->c));
return EXIT_SUCCESS;
}

When I compile (gcc -g -W -Wall -ansi -pedantic) and run the above code,
it prints "addr is [0x4].". If I change to 0 to 100, it prints 104.

Why?

Which part of the standard mandates this behaviour?

Thanks,
--GS
 
R

Raghu

The answer you are getting is correct , becuase in the structure first
element is of integer type , so the "char c " lies 4 bytes away from the
base address you give.
if you interchange position of float f and char c in your structure , the
offset for char c will be 8 from the base address you give.

-Raghu.
 
P

pemo

gokrix said:
#include <stdio.h>
#include <stdlib.h>

struct s
{
int i;
char c;
float f;
};

int main()
{
printf("addr is [%p]. \n", &(((struct s*)0)->c));
return EXIT_SUCCESS;
}

When I compile (gcc -g -W -Wall -ansi -pedantic) and run the above code,
it prints "addr is [0x4].". If I change to 0 to 100, it prints 104.

Why?

Which part of the standard mandates this behaviour?

The logic bit ;-)

You're using 0 -or- 100 as an address, and then casting that to struct s
pointer. You then take the address of the member 'c' - which comes after
member 'i'. i is an int, and appears to be 32-bits with your compiler.
32-bits = 4 bytes. So, addresses 0, 1, 2, 3 are 'i', and therefore 'c'
starts at 4.

Presumably, you actually want a struct s, e.g.,

struct s j;

printf("addr is [%p]. \n", &(((struct s*)&j)->c));
 
G

gokrix

pemo said:
#include <stdio.h>
#include <stdlib.h>

struct s
{
int i;
char c;
float f;
};

int main()
{
printf("addr is [%p]. \n", &(((struct s*)0)->c));
return EXIT_SUCCESS;
}

When I compile (gcc -g -W -Wall -ansi -pedantic) and run the above code,
it prints "addr is [0x4].". If I change to 0 to 100, it prints 104.

Why?


Which part of the standard mandates this behaviour?


The logic bit ;-)

You're using 0 -or- 100 as an address, and then casting that to struct s
pointer. You then take the address of the member 'c' - which comes after
member 'i'. i is an int, and appears to be 32-bits with your compiler.
32-bits = 4 bytes. So, addresses 0, 1, 2, 3 are 'i', and therefore 'c'
starts at 4.

Presumably, you actually want a struct s, e.g.,

struct s j;

printf("addr is [%p]. \n", &(((struct s*)&j)->c));

Maybe I could have framed the question better, along the lines of "Why
is this not an undefined operation?". I was under the impression that
the '->' operation on an address that does not belong to you (say a
random address like 0 or 100) leads to undefined behaviour.

Thanks,
--GS
 
P

pemo

Maybe I could have framed the question better, along the lines of "Why is
this not an undefined operation?". I was under the impression that the
'->' operation on an address that does not belong to you (say a random
address like 0 or 100) leads to undefined behaviour.

Well, yes it does - unless you know what's at address 0, 100 etc.

Were you expecting a seg fault, or a compiler diagnostic, or something else?
 
E

Eric Sosman

gokrix said:
#include <stdio.h>
#include <stdlib.h>

struct s
{
int i;
char c;
float f;
};

int main()
{
printf("addr is [%p]. \n", &(((struct s*)0)->c));
return EXIT_SUCCESS;
}

When I compile (gcc -g -W -Wall -ansi -pedantic) and run the above code,
it prints "addr is [0x4].". If I change to 0 to 100, it prints 104.

Why?

Which part of the standard mandates this behaviour?

No part of the Standard mandates this behavior.
The behavior is undefined, meaning that the Standard
permits anything at all to happen.
 
G

gokrix

pemo said:
Well, yes it does - unless you know what's at address 0, 100 etc.

Were you expecting a seg fault, or a compiler diagnostic, or something else?

Yes, indeed.

Thanks,
--GS
 
G

gokrix

Eric said:
gokrix said:
#include <stdio.h>
#include <stdlib.h>

struct s
{
int i;
char c;
float f;
};

int main()
{
printf("addr is [%p]. \n", &(((struct s*)0)->c));
return EXIT_SUCCESS;
}

When I compile (gcc -g -W -Wall -ansi -pedantic) and run the above
code, it prints "addr is [0x4].". If I change to 0 to 100, it prints
104.

Why?

Which part of the standard mandates this behaviour?


No part of the Standard mandates this behavior.
The behavior is undefined, meaning that the Standard
permits anything at all to happen.

Hmph. I assumed it was ISO C because all three compilers I tried (Sun
C, gcc, MSVC) returned identical results.

Bastard compiler writers. Do they have a union?

Thanks,
--GS
 
S

Skarmander

gokrix said:
Yes, indeed.
Valuable lesson, then: undefined behavior can be anything, including doing
something meaningful.

Evaluating &(((struct s*)0)->c) will not cause a segmentation fault because
gcc sees that this expression has a constant value. It doesn't need to
access any memory to compute it, and therefore it won't.

Change it to ((struct s*)0)->c, however, and you will see a quite different
result on most platforms.

Finally, if you want to know the offset of a struct member in a portable
way, use offsetof().

S.
 
T

Thad Smith

gokrix said:
Eric said:
gokrix said:
printf("addr is [%p]. \n", &(((struct s*)0)->c));
...
Which part of the standard mandates this behaviour?

No part of the Standard mandates this behavior.
The behavior is undefined, meaning that the Standard
permits anything at all to happen.

Hmph. I assumed it was ISO C because all three compilers I tried (Sun
C, gcc, MSVC) returned identical results.

Getting identical results on 3 compiler/target combinations is a poor
predictor of standard behavior. Forexample, most current processors use
two's complement representation and power-of-two bit length integers,
but code depending on that would not be standard-conforming. Reading
the standard is the best way to determine standard behavior. ;-)
 
R

Richard Tobin

Hmph. I assumed it was ISO C because all three compilers I tried (Sun
C, gcc, MSVC) returned identical results.

Undefined behaviour includes the possibility of doing the obvious,
straightforward thing.

-- Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top