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

Home Posts Topics Members FAQ

offsetof() macro

Hi,

Can somebody please help me grok the offsetof() macro?

I've found an explanation on
http://www.embedded.com/shared/print...cleID=18312031
but I'm afraid it still doesn't make sense to me.

The sticking point seems to be:

((s *)0) takes the integer zero and casts it as a pointer to s.

To my untrained eye that would basically result in a null pointer. Does
this expression result in some special behaviour or am I missing
something?

Thanks.

Simon

--
"Being a social outcast helps you stay concentrated on the really important
things, like thinking and hacking." - Eric S. Raymond

Nov 15 '05
44 3759
Keith Thompson <ks***@mib.or g> writes:
Tim Rentsch <tx*@alumnus.ca ltech.edu> writes:
Keith Thompson <ks***@mib.or g> writes: [...]
My idea (which is totally impractical because it would break existing
code) is that the "nil" keyword would be the *only* legal null pointer
constant.


Ahh I see. The revised language would not only add 'nil' but
also would take away '0' (and '(void*)0') as a way of writing
null pointer values. Clearly there are some benefits to using
'nil' as the only form of null pointer constant. What do you
think the costs are, not counting the cost of converting existing
code so that it uses 'nil'? Or have you thought much about what
the costs would be?


I've used other languages that have a keyword that's used as the
equivalent of a null pointer constant, and that don't allow any other
form of null pointer constant. I'll just mention that programmers in
those languages typically don't know or care how null pointers are
represented; even if they happen to know how a given implementation
represents null pointers, they don't try to make use of the knowledge.
And their FAQs don't have to devote an entire section to null
pointers.


Sure; certainly there are some benefits to the 'nil' approach.

I don't think there are any costs to this approach, apart from the
insurmountable cost of all the existing C code that would be broken.
In my experience these kinds of design choices essentially always
carry ongoing costs as well as benefits. That isn't to say that the
benefits won't outweigh the costs necessarily, only that there also
are costs to consider. So if you aren't aware of any costs besides
the cost of converting existing code, maybe you haven't considered
the ramifications fully enough yet?

To put this another way, when C was being designed, there already were
languages with, eg, NULL to indicate null pointers (and no other forms
allowed). Yet KT and/or DR decided to use 0 for null pointers, so
they must have thought there were some benefits to doing that over
using NULL. If the original C model has some benefits, then giving
those up is a cost.

I'm almost tempted to suggest adding a "nil" keyword to the next C
standard, with the obvious semantics, *without* eliminating the other
forms of null pointer constant. But providing a better approach
without removing the old one would just add to the confusion.


Why not just use NULL? A lint-like tool, or a compiler warning
switch, could be used to flag those cases where a pointer value is
needed yet a null pointer constant other than NULL is used. That
approach seems more likely to get to where you hope to get to.
Nov 15 '05 #41
Tim Rentsch <tx*@alumnus.ca ltech.edu> writes:
Keith Thompson <ks***@mib.or g> writes:

[...]
I've used other languages that have a keyword that's used as the
equivalent of a null pointer constant, and that don't allow any other
form of null pointer constant. I'll just mention that programmers in
those languages typically don't know or care how null pointers are
represented; even if they happen to know how a given implementation
represents null pointers, they don't try to make use of the knowledge.
And their FAQs don't have to devote an entire section to null
pointers.


Sure; certainly there are some benefits to the 'nil' approach.
I don't think there are any costs to this approach, apart from the
insurmountable cost of all the existing C code that would be broken.


In my experience these kinds of design choices essentially always
carry ongoing costs as well as benefits. That isn't to say that the
benefits won't outweigh the costs necessarily, only that there also
are costs to consider. So if you aren't aware of any costs besides
the cost of converting existing code, maybe you haven't considered
the ramifications fully enough yet?

To put this another way, when C was being designed, there already were
languages with, eg, NULL to indicate null pointers (and no other forms
allowed). Yet KT and/or DR decided to use 0 for null pointers, so
they must have thought there were some benefits to doing that over
using NULL. If the original C model has some benefits, then giving
those up is a cost.


C was based on a couple of earlier languages. BCPL, if I recall
correctly, was a low-level language that treated all of memory as an
array of words; pointers were effectively indices into that array.

Conceivably there might be some advantage (other than historical) in
C's approach rather than defining single keyword for null pointers. I
just can't think of anything. Can you?
I'm almost tempted to suggest adding a "nil" keyword to the next C
standard, with the obvious semantics, *without* eliminating the other
forms of null pointer constant. But providing a better approach
without removing the old one would just add to the confusion.


Why not just use NULL? A lint-like tool, or a compiler warning
switch, could be used to flag those cases where a pointer value is
needed yet a null pointer constant other than NULL is used. That
approach seems more likely to get to where you hope to get to.


I have no real hope of getting anywhere with this.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #42
Keith Thompson <ks***@mib.or g> writes:
Tim Rentsch <tx*@alumnus.ca ltech.edu> writes:
Keith Thompson <ks***@mib.or g> writes: [...]
C99 6.3.2.3p3 defines the term "null pointer constant":

An integer constant expression with the value 0, or such an
expression cast to type void *, is called a _null pointer
constant_.

I don't see any permission for the implementation to define null
pointer constants that don't meet that definition. 7.17p3 says that
the macro NULL "expands to an implementation-defined null pointer
constant". This allows the implementation to define NULL as either 0,
(void*)0, or ('/'/'/'-'/'/'/'); it doesn't allow it to define NULL as
(void*)(char*)0 . 7.17p3 constrains the implementation' s definition of
NULL; it doesn't define "null pointer constant".


I agree the issue is not clear cut. I wasn't meaning to start a
debate on the issue, only to give a plausible and reasonable
alternative reading. However, since you ask, let me frame some
arguments.


Actually, we aren't in agreement. I think the issue is (reasonably)
clear-cut.


I don't see any inconsistency between saying the issue is reasonably
clear-cut and saying the issue is not clear cut. There's a difference
in degree between the two statements, but they aren't inconsistent.

So I'm not sure that I can agree that we aren't in agreement. :)

1. The Standard isn't always careful in how definitions are given.
There was discussion recently on the definition of "definition ", for
example. Although I think it would be a good idea if the Standard
were more rigorous (and, dare I say it, "mathematic al") in defining
and using special terms, that isn't what it does now.


Agreed. However, there are cases where the standard gives explicit
permission to do something in an implementation-defined way, such as
the declaration of main(). The fact that it doesn't do so here is,
IMHO, significant.


Saying you believe it's significant isn't really a very convincing
argument, is it?

More specifically, look at the wording of 5.1.2.2.1, where 'main' is
specified. Clearly paragraph 1 intends to give a precise
specification of 'main'; in particular, the word "shall" is used.
The wording used in 6.3.2.3 p3 is quite different. The analogy
just doesn't seem strong enough to be very convincing.

2. Note the particular wording in 6.3.2.3 p3: such-and-such kind of
expression *is called* a null pointer constant. It doesn't say the
list is exhaustive. If there are any candidates for definitions in
the Standard that are one-way definitions rather than two-way
definitions, surely the statement in 6.3.2.3 p3 must be one of them.


Since there's a clear and unambiguous interpretation assuming the
definition is exhaustive, I believe that's the best interpretation.


If you want to believe that, it's ok with me. But your statement
doesn't offer me any reason why I should believe it.

Furthermore, there's an obvious reason not to believe it, which is
that interpreted as an exhaustive definition, the given wording is
clearly incomplete since it doesn't cover things like '((void*)0)'.

The standard doesn't give explicit permission for other forms of null
pointer constant. Using (void*)42 in a context that requires a null
pointer constant is a constraint violation. An implementation that
doesn't issue a diagnostic for such a use is non-conforming.
Saying an implementation that doesn't issue a diagnostic for such a
use must be non-conforming is predicated on the assumption that
implementation-defined null pointer constants aren't allowed. It's
circular reasoning.

On the other hand, an implementation certainly is free to choose a
representation for pointers where any address under, say, 100 is to be
interpreted as a null pointer. On such an implementation, it would be
perfectly reasonable for '(void*)42' to be allowed as a null pointer
constant.

Similarly, the standard doesn't give permission for other forms of
integer constants. An implementation can accept 0b11001001 as a
binary constant as a language extension, but it must issue a
diagnostic for any such constant in conforming mode.
Not the same thing at all. The form of integer constants is specified
by syntax rules; these rules have a precise and exact meaning. I
don't have a reference handy, but I believe there is a statement in
the Standard to the effect that a syntax violation must result in a
diagnostic. Certainly using an implementation-defined null pointer
constant *might* result in a diagnostic being issued, but I don't know
of any provision that *requires* one.

3. The mere use of the term "implementa tion-defined null pointer
constants" suggests that there are some null pointer constants that
are defined by the implementation rather than by the Standard.
Otherwise, 7.17 p3 could have said just that "NULL expands to a null
pointer constant". Based on the way other parts of the Standard are
written, the more concise form seems more likely if an implementation
were not allowed to define null pointer constants (perhaps with a
footnote that says, eg, "The choice of which null pointer constant
expression to use is implementation defined.").


The term "implementa tion-defined" doesn't just mean that the
implementation gets to make a choice; it also means it has to document
that choice. If the standard merely said that NULL expands to a null
pointer constant, an implementation wouldn't be required to document
what it actually expands to. This would be no great loss, since code
shouldn't depend on the choice, but I believe the intent is that (a)
an implementation can choose any valid null pointer constant as the
expansion of NULL, and (b) it must document what choice it makes.


That's a plausible interpretation. However, that interpretation seems
better expressed by saying, eg, "NULL expands to a null pointer
constant; the choice of which null pointer constant is implementation
defined." You haven't really given any kind of convincing reason,
merely stated that you believe that's the intent. In the absence of
any such reason, allowing NULL to define an implementation-defined
null pointer constant seems like a better fit to the existing
language, because otherwise that language would probably have been
rewritten to better express the intent you suggest.

It wouldn't make sense to use the phrase "implementa tion defined" only
in a footnote.


I agree that it's better to put the "implementa tion defined" phrase
in the main text, in either interpretation; as mentioned above.

4. If we take 6.3.2.3 p3 as precisely delimiting the set of
expressions that are null pointer constants, then, as you yourself
pointed out, '((void*)0)' would not be a null pointer constant.
Yet

int (*fp)(int);
fp = ((void*)0);

works. (At least, I'm not aware of any implementation where it
doesn't work.) This code isn't allowed to work (without a diagnostic)
unless '((void*)0)' were a null pointer constant. So what are we to
believe? That lots of implementations got it wrong, or that the set
of expressions mentioned in 6.3.2.3 p3 is not exhaustive? The second
alternative seems more likely. If the set of expressions mentioned in
6.3.2.3 p3 is not exhaustive, then of course any additional forms of
null pointer constant would be implementation defined.


I believe the glitch in 6.3.2.3p3, which implies that (void*)0 is a
null pointer constant but ((void*)0) isn't, is simply an oversight. I
suspect the authors of the standard just assumed that an expression in
parentheses is equivalent to the expression without parentheses -- and
of course enclosing macro definitions in parentheses is almost always
a good idea. Implementations actually conform to the intent of the
standard in this case, rather than to the literal wording. I wouldn't
infer anything significant from this (though I'd certainly like to see
this corrected.)


A small correction - implementations conform to what *you presume* the
intent of the standard is. If implementation-defined null pointer
constants are allowed, then they may be conforming to the actual
standard and not just to the intent.

If your suspicion about simply forgetting about enclosing parentheses
were right, then other more complicated forms of "null pointer
constants" shouldn't work. Have you tried any of these? If not
you may be surprised by what you find.

5. In the absence of any clearly compelling argument to the contrary,
the reading that puts less strain on the interpretation seems better.
Basically, Occam's Razor. Unless there is specific evidence that an
implementation is forbidden from defining particular forms of null
pointer constants, it's a better match to the observed facts to
assume that it's allowed.


I disagree. I find it much simpler to assume that the definition of
"null pointer constant" means exactly what it says, modulo the
parentheses glitch. The intent of the phrase "implementa tion-defined
null pointer constant" in 7.17p3 is quite clear given this
interpretation; there's no need to invent the idea of additional
implementation-defined *forms* of null pointer constant. There's also
no advantage in doing so; we have more than enough null pointer
constants already without allowing implementations to invent their
own.


If I may paraphrase, what you think is that the document authors
screwed up, because your interpretation is simpler? Or is it
the other way around?

Perhaps that was a little unfair. But I don't see any real substance
here; if one assumes your position, then everything is consistent and
clear. However that's equally true for the other position. I don't
see any reason, on those grounds, that anyone should prefer one
position over the other.
Nov 15 '05 #43
Tim Rentsch <tx*@alumnus.ca ltech.edu> writes:
Keith Thompson <ks***@mib.or g> writes:
Tim Rentsch <tx*@alumnus.ca ltech.edu> writes: [...]
> 5. In the absence of any clearly compelling argument to the contrary,
> the reading that puts less strain on the interpretation seems better.
> Basically, Occam's Razor. Unless there is specific evidence that an
> implementation is forbidden from defining particular forms of null
> pointer constants, it's a better match to the observed facts to
> assume that it's allowed.


I disagree. I find it much simpler to assume that the definition of
"null pointer constant" means exactly what it says, modulo the
parentheses glitch. The intent of the phrase "implementa tion-defined
null pointer constant" in 7.17p3 is quite clear given this
interpretation; there's no need to invent the idea of additional
implementation-defined *forms* of null pointer constant. There's also
no advantage in doing so; we have more than enough null pointer
constants already without allowing implementations to invent their
own.


If I may paraphrase, what you think is that the document authors
screwed up, because your interpretation is simpler? Or is it
the other way around?

Perhaps that was a little unfair. But I don't see any real substance
here; if one assumes your position, then everything is consistent and
clear. However that's equally true for the other position. I don't
see any reason, on those grounds, that anyone should prefer one
position over the other.


There's not a whole lot more to be said, but I've just posted a
question to comp.std.c. Perhaps we can get an interpretation from the
folks who actually wrote the standard.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #44
Keith Thompson <ks***@mib.or g> writes:
Conceivably there might be some advantage (other than historical) in
C's approach rather than defining single keyword for null pointers. I
just can't think of anything. Can you?


I have my own opinions about what some of these are,
but perhaps we can get some other regulars to voice
their opinions on the subject. I don't want to get
involved in a debate about the relative merits of
the two approaches.
Nov 15 '05 #45

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

Similar topics

5
6348
by: Hiroki Horiuchi | last post by:
Hello. I wrote a program, but g++ warns a.c:11: warning: invalid access to non-static data member `A::y' of NULL object a.c:11: warning: (perhaps the `offsetof' macro was used incorrectly) The program is like below. class A {
9
2970
by: Exits Funnel | last post by:
Consider this code which is a very trimmed down version of some I've inherited and am trying to port from windows to g++: //Begin test1.cpp class foo { int i; int j; }; class bar { bar (int foo::* dataMember) :offsetof (foo, *dataMember) //Call this Line (A)
6
2205
by: Arthur J. O'Dwyer | last post by:
As far as I know, C89/C90 did not contain the now-standard offsetof() macro. Did C89 mandate that structs had to have a consistent layout? For example, consider the typical layout of the following structure: struct weird { int x; /* sizeof(int)==4 here */
13
380
by: luke | last post by:
hi all, i have another question. I've read the FAQ regarding my former question (sizeof struct and union) and in question 2.14 it talks about offset macro. #define offsetof(type, mem) ((size_t) \ ((char *)&((type *)0)->mem - (char *)(type *)0)) Can anyone explain me how it works. 1)I can't understand what "0" casted to (type *) means
7
4540
by: Fred Zwarts | last post by:
Consider the following definition: typedef struct { int a; int b; } s; Now I have a function void f (int i) { ... }
8
5870
by: Pawel | last post by:
Hallo group members. //p1.cpp #include <stdio.h> #include <linux/stddef.h> struct Person { int m_age; char* m_name; };
11
2435
by: Kavya | last post by:
offsetof(T,m) (size_t)&(((T*)0)->m) Why do we always start from 0 in this macro to access the offset of structure or union. Does standard guarantees that structure and union reside at address 0? If yes, then what if I have two or more structures. How can they reside at same address?.
24
3503
by: Francine.Neary | last post by:
Just out of personal curiosity :) What do people use offsetof() for? I mean, I can understand why you'd want to be able to take the address of a member of a struct, but you can do that with just &(s.a) or similar. Why you'd care about the offset (which surely depends on how the compiler chooses to lay the struct out in memory), I don't really know. And if you did really care, won't offset(s,a) just be &(s.a) - &s ?
5
1902
by: mihirtr | last post by:
Hi, I have following structures and union typedef struct { int a; int b; char *c; }TEST_1;
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
10653
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...
0
10137
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
5564
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...
0
5700
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4352
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
3876
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3027
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.