Eric Sosman
6/4/2011 1:44:00 AM
On 6/3/2011 1:57 PM, Shao Miller wrote:
> Good day, folks. I'm pondering 'offsetof()'. 6.6 "Constant expressions"
> might be relevant.
>
> Suppose we've:
>
> int helper[2];
>
> enum foo {
> bar = helper + 1 - helper
> };
>
> int main(void) {
> return 0;
> }
>
> Does that code include any undefined behaviour?
No. Or, rather, "maybe." After emitting the required diagnostic
(for violation of the "shall" in 6.7.2.2p2), the compiler may reject
the program or may accept it and give it an implementation-defined
meaning. That implementation-defined meaning may leave some things
undefined, and if you run into them you'll have undefined behavior.
But you'll have the diagnostic first.
> How about in:
>
> int (* helper)[2];
>
> enum foo {
> bar = *helper + 1 - *helper
> };
>
> int main(void) {
> return 0;
> }
>
> Is there undefined behaviour there? [...]
Ditto.
> So let's please go on to:
>
> char ** helper;
>
> enum foo {
> bar = *helper + 1 - *helper
> };
>
> int main(void) {
> return 0;
> }
>
> Is there undefined behaviour there? [...]
Ditto.
> char ** helper;
>
> struct s {
> int arr[2];
> };
>
> enum foo {
> bar = ((struct s *)*helper)->arr + 1 - ((struct s *)*helper)->arr
> };
>
> int main(void) {
> return 0;
> }
Ditto.
> char ** helper;
>
> struct s {
> int x;
> short y;
> int z;
> };
>
> enum foo {
> bar = (char *)&((struct s *)*helper)->z -
> (char *)((struct s *)*helper)
> };
>
> int main(void) {
> return 0;
> }
Ditto.
> In the example just above, does the value of 'bar' depend on the value
> of 'helper'? Is 'helper' evaluated? If so, what if we use that mess as
> part of a type-name in an operand to 'sizeof', as in:
>
> char ** helper;
>
> struct s {
> int x;
> short y;
> int z;
> };
>
> enum foo {
> bar = sizeof (char[
> (char *)&((struct s *)*helper)->z -
> (char *)((struct s *)*helper)
> ])
> };
>
> int main(void) {
> return 0;
> }
Ditto.
> Could 'offsetof' be reasonably portable as:
>
> char ** helper;
>
> #define DUMMY_OF(type) ((type *)*helper)
> #define ADDRESS_AT(address) ((char *)(address))
> #define DUMMY_MEMBER_ADDRESS(type, member) (&DUMMY_OF(type)->member)
> #define PROTECT(expression) (sizeof (char[(expression)]))
> #define OFFSETOF(type, member) (PROTECT( \
> ADDRESS_AT(DUMMY_MEMBER_ADDRESS(type, member)) - \
> ADDRESS_AT(DUMMY_OF(type)) \
> ))
>
> struct s {
> int x;
> short y;
> int z;
> };
>
> enum foo {
> bar = OFFSETOF(struct s, z)
> };
>
> int main(void) {
> return 0;
> }
No.
> Are there any null pointers or other dragons in there?
No dragons, just diagnostics.
--
Eric Sosman
esosman@ieee-dot-org.invalid