473,811 Members | 2,665 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

struct named 0


Is the following code conformat to ANSI C?

typedef struct {
int a;
int b;
} doomdata;

int main(void)
{
int x;

x = (int)&((doomdat a*)0)->b;
printf("x=%d\n" , x);
return x;
}

The part,
(int)&((doomdat a*)0)->b;

is it conformant to ANSI C? What is it supposed to do?

Thanks for any tips.

Napi

--
http://www.axiomsol.com
http://www.cs.indiana.edu/hyplan/napi.html
Nov 14 '05
60 2965

"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote in message
news:co******** **@newsg3.svr.p ol.co.uk...
"Christian Bau" <ch***********@ cbau.freeserve. co.uk> wrote

In C99, there seems to be an actual requirement that casting an integer
zero to a pointer type will produce a null pointer. If null pointers
don't have all bits zero, and an integer 0 has all bits zero, and
converting an integer 0 to a pointer produces a null pointer, then logic
says that this conversion cannot leave the bits unchanged.

But in this case we are not casting an integer 0 to a pointer, but a null
pointer to an integer.


No, you're not.

You casting integer 0 into a null pointer, offsetting
that pointer by the distance to the member field, then
taking the address of that field (which converts the
pointer back to an integer -- that reverses whatever
happened in converting the integer to a pointer). That
leaves a simple integer constant that can be resolved
at compile time.

The & cancels out the ->. There is no load of a pointer
into an address register whatsoever and no runtime
dereference.

Nov 14 '05 #21
"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote:
"Jack Klein" <ja*******@spam cop.net> wrote


When will people get it through their heads that it makes not a whit
of difference whether all bits zero happens to be a representation of
a null pointer on a particular platform?

Also consider if a null pointer is cast to an integral type, or if a pointer
derived by adding an offset to the null pointer is cast to an integer. This
cast is a simple bitwise conversion, so results will differ on a platform on
which NULL is not all bits zero.


Actually the cast is implementation-defined (and the implementation
can define it to be UB in some, or all, cases).
It would make sense for an implementation to give 0 for
(int)(void *)0, even if (void *)0 were not all bits zero.

The expression (int)&((doomdat a*)0)->b is relying on 2 non-standard
things:
- the compiler doesn't actually dereference 0
- the cast to int works as if pointers are ints in a flat
memory model and (int)NULL == 0

It's irrelevant to this expression whether NULL is all-bits-zero
or not.
Nov 14 '05 #22

"Jack Klein" <ja*******@spam cop.net> wrote in message
news:bn******** *************** *********@4ax.c om...
On 28 Nov 2004 20:29:37 GMT, "S.Tobias"
<si***@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:
Jack Klein <ja*******@spam cop.net> wrote:
On 28 Nov 2004 10:41:21 GMT, "S.Tobias"
<si***@FamOuS.B edBuG.pAlS.INVA LID> wrote in comp.lang.c:
> Mohd Hanafiah Abdullah <na**@cs.indian a.edu> wrote:
> > typedef struct {
> > int a;
> > int b;
> > } doomdata;

> Would this be correct?
> (int)&((doomdat a*)0)->a;

Technically it is still undefined behavior, as the semantics of the
expression dereference a null pointer.


(This deserves a separate thread, but since I asked the above
question here, I'll continue here too.)

As I understand the expression constitutes an access to the structure
member.

1. Does a member access constitute an access to the *whole* structure?
eg.:


The term 'access' is really only used in the C standard in conjunction
with the volatile qualifier, where the wording is unfortunately vague
enough that it can be construed several different ways.
struct A { int i; int _i; };
struct B { int i; float f; };
struct A a = {0};
struct B *pb = (struct B*)&a;
pb->i; //UB?
(*pb).i; //UB?


The two statements above actually have defined behavior, but not for
the reason you might think. The language guarantees that a pointer to
structure, suitably cast, is also a pointer to its first member. So
in given that 'pb' holds any of the following:

- a pointer to any structure type whose first member is an int

- a pointer to an array of ints

- a pointer to a single int

...and the int pointed to has a valid value, the expressions, though
not recommended, will work as designed. The compiler must generate
code equivalent to *(int *)pb, and if there is actually an int there
all is well.
Do I access the first int sub-object in `a' only, or do I access
the whole object `a'?


Now that depends what you mean by access. Let's assume a Pentium
(1/2/3/4) platform with a typical compiler, which means the size of
either of your structures is 8 8-bit bytes. Now let's also assume
that this implementation allocates all structures on an address evenly
divisible by 8, a not uncommon performance feature of such
implementations .

With the assumptions above, if the processor needs to access the
structure from memory it will perform a 64-bit access physically, so
even though your code does not direct the abstract machine to touch
the value of other members in any way, the entire memory space holding
the structure will be physically read.
2. I see certain similarity between structs and arrays (in fact,
both are called "aggregates ").
Why is it that for array:
&a[5];
doesn't constitute object access (6.5.3.2#3), whereas for struct:
&s.m;
&ps->m;
the expressions do constitute access?
Why is the language designed like this?


There are actually more differences than similarities between structs
and arrays, despite the fact that both are aggregates. Structs are
first class objects, meaning they can be assigned, passed to and
returned from functions by value, and their names are never implicitly
converted to pointers. Arrays are not first class objects and do not
share any of the characteristics above.

As for other differences in this particular case, this is spelled out
by paragraph 3 of 6.5.3.2 of C99:

[begin quotation]
The unary & operator returns the address of its operand. If the
operand has type ''type'', the result has type ''pointer to type''. If
the operand is the result of a unary * operator, neither that operator
nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and
the result is not an lvalue. Similarly, if the operand is the result
of a [] operator, neither the & operator nor the unary * that is
implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator.
Otherwise, the result is a pointer to the object or function
designated by its operand.
[end quotation]

Note the differences between applying '&' to the result of a '*'
operator and to the result of a '[]' operator. In the former case,
neither '&' nor '*' are evaluated as such, but note "the constraints
on the operators still apply".

Now let's back up to paragraph 1 of 6.5.3.2, which lists the
constraints for the unary '&' operator:

[begin quotation]
The operand of the unary & operator shall be either a function
designator, the result of a [] or unary * operator, or an lvalue that
designates an object that is not a bit-field and is not declared with
the register storage-class specifier.
[end quotation]

Notice that the expression under discussion,

(int)&((doomdat a*)0)->a;

...is none of these things. Specifically, the operand of the '&'
operator, '((doomdata*)0)->a' is:

- not a function designator

- not the result of a [] operator

- not the result of a unary * operator


Yes it is unary *. a->b is an alias for (*a).b
- and, because of the null pointer, not an lvalue

Finally consider one last thing, namely that regardless of whether
there is an actual access to an object, the expression explicitly
performs pointer arithmetic on a null pointer, and such use of a null
pointer is undefined in and of itself.


Therefore, & cancels out the -> to yield a simple
integer constant that is resolved at compile time.
Nov 14 '05 #23
In article <q1************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:
... the compiler will not generate a load into an address register,
because the & cancels out the ->. The compiler has all the information
it needs to resolve the expression to a constant offset value.


There is only one problem: the compiler really sucks. It does
only what it is absolutely forced to by the C Standard. The C
Standard *allows* it to follow the pointer first, and only then
compute the offset, so it does.

(Well, which "the" compiler are *you* talking about?)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #24
"Chris Torek" <no****@torek.n et> wrote in message
news:co******** *@news2.newsguy .com...
In article <q1************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:
... the compiler will not generate a load into an address register,
because the & cancels out the ->. The compiler has all the information
it needs to resolve the expression to a constant offset value.


There is only one problem: the compiler really sucks. It does
only what it is absolutely forced to by the C Standard. The C
Standard *allows* it to follow the pointer first, and only then
compute the offset, so it does.


Following the pointer into memory would make it
impossible to determine the address of the field.

The & cancels out the apparent dereference.
Nov 14 '05 #25
>> In article <q1************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:
>... the compiler will not generate a load into an address register,
>because the & cancels out the ->. The compiler has all the information
>it needs to resolve the expression to a constant offset value.
"Chris Torek" <no****@torek.n et> wrote in message
news:co******* **@news2.newsgu y.com...
There is only one problem: the compiler really sucks. It does
only what it is absolutely forced to by the C Standard. The C
Standard *allows* it to follow the pointer first, and only then
compute the offset, so it does.

In article <PU************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:Following the pointer into memory would make it
impossible to determine the address of the field.
Yes. This is why the compiler throws the result away after following
the pointer.
The & cancels out the apparent dereference.


No, the "&" makes the compiler throw away the result of the dereference.

Unfortunately, by then it is too late.

I did say this compiler really sucks. But it conforms.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #26
"Chris Torek" <no****@torek.n et> wrote in message
news:co******** *@news2.newsguy .com...
In article <q1************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:
>... the compiler will not generate a load into an address register,
>because the & cancels out the ->. The compiler has all the information
>it needs to resolve the expression to a constant offset value.

"Chris Torek" <no****@torek.n et> wrote in message
news:co******* **@news2.newsgu y.com...
There is only one problem: the compiler really sucks. It does
only what it is absolutely forced to by the C Standard. The C
Standard *allows* it to follow the pointer first, and only then
compute the offset, so it does.


In article <PU************ *****@newsread3 .news.pas.earth link.net>
xarax <xa***@email.co m> wrote:
Following the pointer into memory would make it
impossible to determine the address of the field.


Yes. This is why the compiler throws the result away after following
the pointer.
The & cancels out the apparent dereference.


No, the "&" makes the compiler throw away the result of the dereference.

Unfortunately, by then it is too late.

I did say this compiler really sucks. But it conforms.


Totally ridiculous.
Nov 14 '05 #27
"xarax" <xa***@email.co m> wrote:
"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote:
"Christian Bau" <ch***********@ cbau.freeserve. co.uk> wrote:

In C99, there seems to be an actual requirement that casting an integer
zero to a pointer type will produce a null pointer. If null pointers
don't have all bits zero, and an integer 0 has all bits zero, and
converting an integer 0 to a pointer produces a null pointer, then logic
says that this conversion cannot leave the bits unchanged.
But in this case we are not casting an integer 0 to a pointer, but a null
pointer to an integer.


No, you're not.

You casting integer 0 into a null pointer,


Casting 0 to a pointer must give a null pointer.
offsetting that pointer by the distance to the member
field, then taking the address of that field
(which converts the pointer back to an integer
That conversion is implementation-defined
-- that reverses whatever happened in converting the
integer to a pointer).
There is no requirement for that to be true. In fact
it can't be true, if there is not an exact mapping
from integers to pointers (eg. segmented architecture,
IA64, etc.)

If you're still not convinced, imagine that NULL
lives at address 0xDEADBEEF. Then &((foo *)0)->bar
might be 0xDEADC00C, for example, and when that's
converted back to an integer you might get 0xDEADC00C
still. Not a very accurate struct offset.
Furthermore, if that is outside the range of signed int
(likely on a 32-bit system) you get undefined behaviour
(again).
That leaves a simple integer constant that can be resolved
at compile time.

There is no load of a pointer into an address register
whatsoever and no runtime dereference.


For your compiler on Tuesdays, perhaps. There is nothing
(except possible sales figures..) to stop a compiler from
loading 0 to an address register and then incrementing
it, causing a hardware exception.
Nov 14 '05 #28
In article <f3************ *************** *****@4ax.com>,
Jack Klein <ja*******@spam cop.net> wrote:
On Sun, 28 Nov 2004 22:17:21 +0000, Christian Bau
<ch***********@ cbau.freeserve. co.uk> wrote in comp.lang.c:
In article <co**********@n ews7.svr.pol.co .uk>,
"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote:
Also consider if a null pointer is cast to an integral type, or if a
pointer
derived by adding an offset to the null pointer is cast to an integer.
This
cast is a simple bitwise conversion, so results will differ on a platform
on
which NULL is not all bits zero.
Not quite; a conversion from a pointer type to an integer does whatever
the implementation thinks is a good idea; usually the bits of the
representation are copied unchanged, but that is not necessarily so.

In C99, there seems to be an actual requirement that casting an integer
zero to a pointer type will produce a null pointer. If null pointers
don't have all bits zero, and an integer 0 has all bits zero, and
converting an integer 0 to a pointer produces a null pointer, then logic
says that this conversion cannot leave the bits unchanged.


I am unsure of your meaning here. Do you mean an integral constant at
the source level, as in:

double *dp = (double * 0);

(double *) 0;
...or do you actually mean the value of an integer object, as in:

int x = 0;
double *dp = (double *x);
Both.
If you mean the latter, I have never noticed anything in C99 requiring
the result be a null pointer.

Could you please clarify and include chapter & verse?


Not directly. The result of conversion from int to for example double*
is defined directly in one special case: When the int is a null pointer
constant, that is the value is 0, and it is an integer constant
expression. But since the result of a conversion only depends on the
value converted and nothing else, the result of converting _any_ int of
value 0 must always be the same. As it is a null pointer in some cases,
it must be a null pointer in all cases.
Nov 14 '05 #29
Christian Bau <ch***********@ cbau.freeserve. co.uk> wrote:
The result of conversion from int to for example double*
is defined directly in one special case: When the int is a null pointer
constant, that is the value is 0, and it is an integer constant
expression.
No, the value is not important here, you're misquoting the Standard.
The Standard says: "integer constant expression with the value 0",
so first you look up what is an integer constant expression, and
then you filter only those that have the value zero. Examples are:
0
0x0
0u
(1-1)
'\000'
(int)0.0
7/11
sizeof 13 - sizeof (int)
But since the result of a conversion only depends on the
value converted and nothing else, the result of converting _any_ int of
value 0 must always be the same. As it is a null pointer in some cases,
it must be a null pointer in all cases.


The Std does not say such a thing. If it wanted the value 0 to be
converted into a null pointer, it would say "integer expression with
the value 0" or just "integer value 0". Integer constant expression
is a special case that a compiler must recognize at compile-time.

Conversions between pointer and integer types are explicitly
implementation defined.

--
Stan Tobias
mailx `echo si***@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
12064
by: James Harris | last post by:
Having updated my Debian system it now complains that I am using an incompatible pointer type in warnings such as "passing arg 2 of 'bind' from incompatible pointer type" from code, struct sockaddr_in sockad1; .... retval = bind (sock1, &sockad1, sockad1len); I can coerce the pointer with
5
2856
by: jimjim | last post by:
Hello, Any help will be much appreciatted. My problem is as follows: I declare as global variables: typedef struct _Node{ ..; ..;}Node; Node *Graph; in a function called initiallise(), I allocate memory and copy information: for(i )
2
5062
by: Peter Dunker | last post by:
Hi, I will write ANSI C89. Is the following struct defenition correct ? I wrote it with VC6(Windows IDE) and at first no Problem. As I changed a compiler switch to 'no language extension', the compiler said that the union has no name. Is it right that in ANSI C the union must be named inside this kind of structure ?
5
3308
by: PCHOME | last post by:
Hello! I am working on dividing a single C file into several files. Now I encounter a problem about the global variables and can not find a way to solve it. All global variables and codes used to be in that single file, that worked OK. But when I divdie that file into several ones, I have many "invalid use of undefined type" errors. The four files are main.c, main.h, readLP.h, and readLP.c. In readLP.h
4
1516
by: lp-boy | last post by:
Hello! Is the following code legal? template<class T> struct holder{}; struct A { holder<struct B*> h; //!!!
9
7213
by: werasm | last post by:
Hi all, What is the difference between: typedef struct { ... } MyS1; ....and...
28
4720
by: Bill | last post by:
Hello All, I am trying to pass a struct to a function. How would that best be accomplished? Thanks, Bill
2
281
by: beet | last post by:
Hi all, I tried to declare a c++ struct like following in a header file; I want to include this header file in other files to create and access this struct. ------ 1 #ifndef _SEARCHDATA_H_ 2 #define _SEARCHDATA_H_ 3
6
368
by: BIll Cunningham | last post by:
pg 128 of kandr2 speaks of a struct struct point{ int x; int y; }; I understand this but what is it saying about using intialize variables like such.
4
1854
by: Lew Pitcher | last post by:
(having trouble getting my reply through - hopefully, third time is a charm) On November 11, 2008 19:53, in comp.lang.c, BIll Cunningham (nospam@nspam.invalid) wrote: Why an int? Because K&R chose to use an int. Why not a double? Because K&R chose to use an int. Note the phrase "syntactically analogous". It means that the /syntax/ of
0
9734
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10652
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10395
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10408
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9211
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5561
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4346
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3874
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3026
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.