Jump to content

Talk:Offsetof

Page contents not supported in other languages.
From Wikipedia, the free encyclopedia

union?

[edit]
  • It evaluates to the offset (in bytes) of a given member within a struct or union type [...]
    • But a union's member all start at the same address, thereby this macro would only return 0, rendering it trivial for union types.

--Abdull (talk) 13:26, 6 August 2008 (UTC)[reply]

The member-designator argument can be a sequence of struct/union members and possibly array indices. So given
union foo { int x ; struct { double a, b; } y[]; };
one may usefully (and validly) write offsetof(union foo, y[10].b). The article could be clearer about this. –Henning Makholm (talk) 17:25, 5 November 2010 (UTC)[reply]

"Modern compilers"

[edit]

The article asserts that the crufty old &((struct foo*)NULL).bar idiom doesn't do the expected on modern compilers. My experience doesn't bear this out... 128.2.100.148 (talk) 10:30, 17 October 2010 (UTC)[reply]

I find this claim dubious too. I suspect it may have originated as an attempt to explain why there are builtins for it in many compilers. I have removed it as unsourced speculation. –Henning Makholm (talk) 17:13, 5 November 2010 (UTC)[reply]

I think the claim is false. Here is Section 6.6 Paragraph 9 from the late draft of the C99 standard cited in the Wikipedia C99 article.

An address constant is a null pointer, a pointer to an lvalue 
designating an object of static storage duration, or a pointer 
to a function designator; it shall be created explicitly using 
the unary & operator or an integer constant cast to pointer type, 
or implicitly by the use of an expression of array or function type. 
The array-subscript [] and member-access . and -> operators, the 
address & and indirection * unary operators, and pointer casts may 
be used in the creation of an address constant, but the value of an 
object shall not be accessed by use of these operators.

So &(struct foo *)0->somefield is a valid address constant (assuming somefield is not a bit field). The numeric value of the address is the offset in bytes from the beginning of the structure, and hence must be smaller than the sizeof(struct foo), and furthermore it is non-negative. Hence it is safe to cast it to size_t.

If I don't hear any objections in the next few days, I'll rewrite the section to not say that the behavior of the historical macro is undefined. DMJ001 (talk) 21:32, 26 February 2011 (UTC)[reply]

I don't think it convincing to say that &(struct foo *)0->somefield is valid. Section 6.6 also states
The semantic rules for the evaluation of a constant expression are the same as for
nonconstant expressions.

Section 6.5.3.2 Paragraph 4 (which is a semantic rule) states

If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.83)

and footnote 83 says

Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an
address inappropriately aligned for the type of object pointed to, and the address of an object after the
end of its lifetime.

(emphasis mine)

As far as I can see, this means &(struct foo *)0->somefield (which, as equivalent to &(*(struct foo *)0).somefield, contains the action of dereferencing a null pointer) does produce an undefined behavior, regardless the fact that &(struct foo *)0->somefield is a constant expression. --D41D8CD98F (talk) 14:09, 14 December 2014 (UTC)[reply]

But section 6.6 Constant Expressions, Paragraph 9, the states that value of the object is not accessed by the operations of using &, *, or ->, so there is no null pointer dereferencing occurring as some suggest. — Preceding unsigned comment added by 68.40.190.43 (talk) 05:49, 5 February 2019 (UTC)[reply]

[edit]

Are you sure that it is not a copyright violation to include GPL2-licensed code of the Linux kernel code (as currently in this article) on Wikipedia? — Preceding unsigned comment added by 193.40.6.84 (talk) 09:27, 21 May 2012 (UTC)[reply]

Why would it be? 190.60.93.218 (talk) 19:08, 8 August 2012 (UTC)[reply]

The container_of macro originates in BSD (at least in 4BSD, possibly earlier). That's probably a better source than the Linux kernel anyway... — Preceding unsigned comment added by 109.223.126.221 (talk) 14:33, 23 December 2015 (UTC)[reply]

Undefined behavior for offsetof

[edit]

It is unclear whether or not the undefined behavior is referring to the particular macro implementation or offsetof. Overdamped (talk) 14:26, 12 June 2013 (UTC)[reply]

It is referring to that particular macro implementation of offsetof. Compilers can implement special builtin versions of offsetof that don't have to invoke undefined behaviour. 217.34.231.28 (talk) 15:12, 16 June 2016 (UTC)[reply]
It should also be noted that implementations can use any particular macro implementation for offsetof(), while knowingly or purposefully designing the semantics of the compiler so that the macro does not invoke undefined behavior for a particular target architecture. — Loadmaster (talk) 22:20, 16 June 2016 (UTC)[reply]

Example uses a GNU C extension which is non-standard

[edit]

The macro container_of makes use of the "statement expressions" extension that GCC defines. See this page for more details: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

This extension is not standard C or C++, so its use in this example should be explicitly noted (or the example should be replaced with one that does not use non-standard language extensions) — Preceding unsigned comment added by 64.94.36.4 (talk) 20:03, 15 November 2016 (UTC)[reply]

"suspicious" results

[edit]

The article states: "... there are edge cases when offsetof will either yield an incorrect value, generate a compile-time warning or error, or outright crash the program. This is especially the case for virtual inheritance.[8] The following program will generate several warnings and print obviously suspicious results..."

However, I think the author(s) has/have neglected the contribution from the virtual methods. Using Microsoft Visual Studio the not so well known compile time flag /d1reportAllClassLayout reveals better the class structure, including the virtual tables. Comparing the output from /d1reportAllClassLayout and offsetof() reveals the stated "...obviously suspicious results..." is incorrect. Using the gcc compiler we can alternatively use the compile time flag -fdump-class-hierarchy. — Preceding unsigned comment added by 195.11.244.2 (talk) 10:52, 26 April 2017 (UTC)[reply]