Accessing structure members indirectly

K

Kavya

Here is the code

int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}

Will the last printf always result in correct output? Is it safer to
access data members of structure this way?
 
J

Jens Thoms Toerring

Kavya said:
Here is the code
int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}
Will the last printf always result in correct output? Is it safer to
access data members of structure this way?

You are guaranteed that address of the first element of a structure
is always at the address of the structure, so you can safely access
the member 'a' of your structure that way (if it's a good idea is
a totally different question). For the other members it's not safe,
e.g.

printf( "%d", * (int *) ((char *) ptr + sizeof(int)));

is _not_ guranteed to print out the value you stored in the member
'b' since the compiler is allowed to insert as many padding bytes
between the structure members as it likes.

Regards, Jens
 
B

Bart

Kavya said:
Here is the code

int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}

Will the last printf always result in correct output? Is it safer to
access data members of structure this way?

Why not just use an array instead of inventing convoluted ways to shoot
yourself in the foot?

Regards,
Bart.
 
R

Richard Bos

Kavya said:
Here is the code

int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}

Will the last printf always result in correct output?

Yes, for the first member. The first member of a struct must always have
the same address as the struct itself. This is required by the Standard.
For any other member, you don't know that. There could be padding
between a and b, so ((int *)&s)+1 might not point at s.b.
Is it safer to access data members of structure this way?

Not at all. Accessing them normally is the best way.

Richard
 
W

Walter Roberson

Kavya said:
Here is the code
int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}
Will the last printf always result in correct output?

You haven't defined what output it is that you feel to be "correct".
Is it safer to
access data members of structure this way?

Safer than what??

What the C standards say is that:

1) the first named member of the structure will always be at offset 0
from the beginning of the structure

2) each additional member will be placed in increasing address order

3) there may be internal padding at any point after the first member,
including at the end of the structure

4) bitfields generally follow the increasing address rule, but the order
of the bits within the internal storage allocation size that
the implementation uses for bitfields, is up to the implementation


5) special meaning for a bitfield width of 0


The first rule ensures that in your example *(int *)&s corresponds
to s.a. However, *(1 + (int *)&s) will *not* necessarily be s.b
because of rule 3.
 
C

Christopher Benson-Manica

Kavya said:
int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}
Will the last printf always result in correct output?

No, but only because it is implementation-defined whether a newline
is required after the last line of output:

printf("%d\n",*(int*)ptr);

P.S. Main returns int, but you didn't return one. Do so and make your
execution environment happy.
 
K

Kavya

Christopher said:
No, but only because it is implementation-defined whether a newline
is required after the last line of output:

Sorry. I didn't get that.
P.S. Main returns int, but you didn't return one. Do so and make your
execution environment happy.

Isn't that implicit?
 
C

Christopher Benson-Manica

Sorry. I didn't get that.

The English version of that sentence is "Things might not work like
you expect if you don't end your output with a newline."
Isn't that implicit?

Only in C99; you are probably not using a C99 compiler. (In English:
There are two different standards that govern the C language - C89 and
C99; many or most C compilers conform to C89 rather than C99. In C89,
if you fail to return a value from main, your shell or whatever you're
executing your program in gets a random return value.)
 
K

Kavya

Christopher said:
The English version of that sentence is "Things might not work like
you expect if you don't end your output with a newline."



Only in C99; you are probably not using a C99 compiler. (In English:
There are two different standards that govern the C language - C89 and
C99; many or most C compilers conform to C89 rather than C99. In C89,
if you fail to return a value from main, your shell or whatever you're
executing your program in gets a random return value.)

Thanks for the these pointers.
 
N

Nick Keighley

Kavya said:
Here is the code

int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}

Will the last printf always result in correct output? Is it safer to
access data members of structure this way?

is offsetof() any use to you? I'm not sure what you are trying to do.


--
Nick Keighley

And so when you think of the future,
imagine a Pentium stamping on a man's face,
forever.
 
A

Andrew Poelstra

Here is the code

int main(){
struct node{
int a;
int b;
int c;
};
struct node s={3,5,6};
struct node *ptr=&s;
printf("%d",*(int*)ptr);
}

Will the last printf always result in correct output? Is it safer to
access data members of structure this way?

I'm pretty sure that "(int) *ptr" will be equally valid and predictable.
Unfortunately, neither /is/ predictable, so it depends on what you mean
by "correct" output.

I believe there is no undefined behaviour, which may be a good
definition of "correct". (Of course, I could be wrong.)
 
A

Andrew Poelstra

I missed your struct definition above. Yes, this is in fact correct and
predictable, but only for the first element. (As has been noted by
others.)
 
K

Keith Thompson

Andrew Poelstra said:
I'm pretty sure that "(int) *ptr" will be equally valid and predictable.
Unfortunately, neither /is/ predictable, so it depends on what you mean
by "correct" output.

*ptr is of type struct node; you can't convert a struct value to int.
 
A

Ark

Jens said:
You are guaranteed that address of the first element of a structure
is always at the address of the structure, so you can safely access
the member 'a' of your structure that way (if it's a good idea is
a totally different question). For the other members it's not safe,
e.g.

printf( "%d", * (int *) ((char *) ptr + sizeof(int)));

is _not_ guranteed to print out the value you stored in the member
'b' since the compiler is allowed to insert as many padding bytes
between the structure members as it likes.

However, b can be portably printed using
printf("%d", *(int*)((char*)ptr + offsetof(struct node, b)));

As to the wisdom of this technique... Occasionally, one may need/want to
parse data consisting of "derived types" like
struct type1 {
int RTTI;
struct base_t base;
struct type1_specific more;
};
struct type3 {
int RTTI;
struct base_t base;
struct type3_specific more;
};
Here, an offsetof-based technique may be useful.

- Ark
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top