473,811 Members | 3,314 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 2964
Mohd Hanafiah Abdullah wrote:

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

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

#include <stdio.h>
#include <stddef.h>

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

int main(void)
{
int x;
#if 0
/* mha: the following is an attempt to mimic offsetof on an
implementation not having offsetof in <stddef.h> */
x = (int) &((doomdata *) 0)->b;
#endif
x = offsetof(doomda ta, b);
printf("x=%d\n" , x);

return 0; /* mha: returning x, when x is not one
of 0, EXIT_SUCCESS, or EXIT_FAILURE
is at best implementation-defined */
}
Nov 14 '05 #11
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.:
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?
Do I access the first int sub-object in `a' only, or do I access
the whole object `a'?

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?

--
Stan Tobias
mailx `echo si***@FamOuS.Be dBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #12
"Jack Klein" <ja*******@spam cop.net> wrote in message
news:ov******** *************** *********@4ax.c om...
On Sun, 28 Nov 2004 11:26:06 +0100, Michael Mair
<Mi**********@i nvalid.invalid> wrote in comp.lang.c:
Mohd Hanafiah Abdullah wrote:
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?


According to prior discussions, it is at least shady but
probably not conformant, depending on whether the address
0 is dereferenced or not.


No it has undefined behavior, and has nothing to do with the "address
0", but with a null pointer. C is defined in terms of an abstract
machine, and in the abstract machine this expression dereferences a
null pointer.

/snip/

It does not dereference any pointer. The & cancels out
the ->.

btw: If the dereference actually happened, how could the
compiler figure out the address of an int that was produced
by the dereference?

Nov 14 '05 #13
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.
Nov 14 '05 #14
"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.
Nov 14 '05 #15

"xarax" <xa***@email.co m> wrote

It does not dereference any pointer. The & cancels out
the ->.

However it is illegal even to load a non-valid pointer, except NULL or
course, into a pointer variable.
One reason is that some platforms have hardware traps that trigger an error
when illegal values are loaded into address registers. Another reason is
that sometimes with segmented architectures you can get strange results. For
instance if char *ptr points to the beginning of a segment, then ptr - 1
might compare to greater than ptr. The address of NULL + a few bytes is an
illegal value, and I don't believe that the cast to an int makes the
expression a legal one, though I am open to correction on this.
Nov 14 '05 #16
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

- 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.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #17
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);

....or do you actually mean the value of an integer object, as in:

int x = 0;
double *dp = (double *x);

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?

Thanks.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #18
On Sun, 28 Nov 2004 19:40:02 -0000, "Malcolm"
<ma*****@55bank .freeserve.co.u k> wrote in comp.lang.c:

"Jack Klein" <ja*******@spam cop.net> wrote
> The part,
> (int)&((doomdat a*)0)->b;
>
> is it conformant to ANSI C? What is it supposed to do?
>
This is the offsetof() macro, which calculates the offset of a structure
member relative to the struct origin.
No, it can't be the offsetof() macro. This expression specifically
yields an int, whereas the offsetof() macro yields a size_t. This
expression yields undefined behavior.

This is true. int is not guaranteed to be big enough to hold the offset of a
structure element (!).

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?

Unfortunately it does make a difference.
For instance consider

char **list = calloc(N, sizeof(char *));


What is the above supposed to prove? It most specifically does not
guarantee to set the N pointers in list to NULL. Setting all bits to
0 with calloc() or memset() is a run-time operation and has nothing at
all to do with the compiler-time conversion of constant expressions to
null pointer constants.
for(i=0;i<N;i++ )
if( someconditon() )
list[i] = malloc(10);

for(i=0;i<N;i++ )
free(list[i]);
This code is badly broken, what is the point?
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.
Again, what is your point. Casting a pointer, null or not, to an
integral type, is defined if and only if there is an integral type
large enough, but let's assume and bypass that. The operation of the
cast is completely implementation-defined, thus automatically neither
portable nor strictly conforming. If you do such a thing, it is up to
you to take such implementation-defined behavior into account as a
part of anything and everything you do with those integers.

As for adding an offset to a null pointer, that is undefined period.
However char *ptr = 0; will always set ptr to NULL, regardless of whether
the null pointer is all bits zero. Here you are correct.


Yes, because this is a compile-time conversion, which happens during
source code translation. This is no more or less remarkable than the
fact that:

char a1 [3] = "\n";
char a2 [3];
a2[0] = '\\';
a2[1] = 'n';
a2[3] = '\o';

....will produce two strings that will not test equal under any string
or memory comparison function.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Nov 14 '05 #19

"Malcolm" <ma*****@55bank .freeserve.co.u k> wrote in message
news:co******** **@newsg4.svr.p ol.co.uk...

"xarax" <xa***@email.co m> wrote

It does not dereference any pointer. The & cancels out
the ->.

However it is illegal even to load a non-valid pointer, except NULL or
course, into a pointer variable.
One reason is that some platforms have hardware traps that trigger an error
when illegal values are loaded into address registers. Another reason is
that sometimes with segmented architectures you can get strange results. For
instance if char *ptr points to the beginning of a segment, then ptr - 1
might compare to greater than ptr. The address of NULL + a few bytes is an
illegal value, and I don't believe that the cast to an int makes the
expression a legal one, though I am open to correction on this.


Notwithstanding what you 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.
Nov 14 '05 #20

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
1515
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
10651
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
10393
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
10405
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
10136
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9208
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
6893
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5556
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...
2
3871
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3020
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.