Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #5368 > unrolled thread

offsetof() Macro Attempt

Started byShao Miller <sha0.miller@gmail.com>
First post2011-06-03 13:57 -0400
Last post2011-06-03 19:46 -0700
Articles 20 on this page of 52 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-03 13:57 -0400
    Re: offsetof() Macro Attempt Billy Mays <noway@nohow.com> - 2011-06-03 13:59 -0400
      Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-03 14:33 -0400
        Re: offsetof() Macro Attempt Noob <root@127.0.0.1> - 2011-06-08 15:03 +0200
    Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-03 14:48 -0400
      Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 02:02 -0500
        Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-04 06:49 -0400
          Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 09:32 -0500
            Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-04 12:55 -0400
              Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 13:24 -0500
                Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-04 14:56 -0400
                  Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-04 15:38 -0400
                    Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 18:25 -0500
                      Re: offsetof() Macro Attempt pete <pfiland@mindspring.com> - 2011-06-05 07:10 -0400
    Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-03 13:39 -0700
      Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-03 19:58 -0700
        Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-04 01:57 -0700
          Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-04 05:22 -0700
            Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-04 10:16 -0700
              Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-04 23:03 -0700
                Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-05 02:24 -0700
                  Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-06 08:08 -0700
                    Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-06 13:26 -0700
                      Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-08 12:34 -0700
                        Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-08 15:07 -0700
                          Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-08 15:19 -0700
                            Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-14 14:53 -0700
                          Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-14 14:52 -0700
                            Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-14 16:24 -0700
                              Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-15 06:44 -0700
                                Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-15 10:40 -0700
                                  Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-19 13:48 -0700
                                    Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-19 14:57 -0700
                                      Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-23 00:52 -0700
                                        Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-23 12:34 -0700
                                          Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-27 10:03 -0700
                                            Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-07-01 10:03 -0700
                                              Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-07-03 14:33 -0700
                                Re: offsetof() Macro Attempt Michael Press <rubrum@pacbell.net> - 2011-06-18 21:17 -0700
                                  Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-27 10:13 -0700
      Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 14:05 -0500
        Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-05 02:44 -0700
          Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-06 17:58 -0500
            Re: offsetof() Macro Attempt Harald van Dijk <truedfx@gmail.com> - 2011-06-06 15:37 -0700
              Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-06 18:58 -0500
    Re: offsetof() Macro Attempt Andrey Tarasevich <andreytarasevich@hotmail.com> - 2011-06-03 17:15 -0700
      Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-03 20:20 -0700
      Re: offsetof() Macro Attempt Shao Miller <sha0.miller@gmail.com> - 2011-06-04 12:50 -0500
    Re: offsetof() Macro Attempt Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-06-03 21:43 -0400
      Re: offsetof() Macro Attempt Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-06-03 21:54 -0400
        Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-03 20:36 -0700
    Re: offsetof() Macro Attempt Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-03 19:46 -0700

Page 1 of 3  [1] 2 3  Next page →


#5368 — offsetof() Macro Attempt

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-03 13:57 -0400
Subjectoffsetof() Macro Attempt
Message-ID<isb79p$oao$1@dont-email.me>
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?

How about in:

   int (* helper)[2];

   enum foo {
       bar = *helper + 1 - *helper
     };

   int main(void) {
       return 0;
     }

Is there undefined behaviour there?  Note that '*helper' is an array 
which "decays" to a pointer to the first element.  Also note that 
'helper' is a pointer to 'int[2]'.  But does it matter what the stored 
value of 'helper' is or is the value of 'bar' independent of it?

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?  So what about in:

   char ** helper;

   struct s {
       int arr[2];
     };

   enum foo {
       bar = ((struct s *)*helper)->arr + 1 - ((struct s *)*helper)->arr
     };

   int main(void) {
       return 0;
     }

?  And then:

   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;
     }

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;
     }

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;
     }

Are there any null pointers or other dragons in there?

Thanks for any insight you can provide!

[toc] | [next] | [standalone]


#5369

FromBilly Mays <noway@nohow.com>
Date2011-06-03 13:59 -0400
Message-ID<isb7f4$80h$3@speranza.aioe.org>
In reply to#5368
 > ...
> #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;
> }
>
> Are there any null pointers or other dragons in there?
>
> Thanks for any insight you can provide!


As far as I can tell, it deterministically returns 0 every time.

--
Bill

[toc] | [prev] | [next] | [standalone]


#5372

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-03 14:33 -0400
Message-ID<isb9d1$63n$1@dont-email.me>
In reply to#5369
On 6/3/2011 13:59, Billy Mays wrote:
>
> As far as I can tell, it deterministically returns 0 every time.

LOL.  Thanks.  In your response, the code has lost its indentation.  Do 
you see indentation in the original code sections?

[toc] | [prev] | [next] | [standalone]


#5637

FromNoob <root@127.0.0.1>
Date2011-06-08 15:03 +0200
Message-ID<isnruc$80k$1@speranza.aioe.org>
In reply to#5372
Shao Miller wrote:

> In your response, the code has lost its indentation.

It's a known bug in Thunderbird's flowed format handling :-(

cf. https://bugzilla.mozilla.org/show_bug.cgi?id=625961

[toc] | [prev] | [next] | [standalone]


#5373

Frompete <pfiland@mindspring.com>
Date2011-06-03 14:48 -0400
Message-ID<4DE92C83.824@mindspring.com>
In reply to#5368
Shao Miller wrote:
 
> So let's please go on to:
> 
>    char ** helper;
> 
>    enum foo {
>        bar = *helper + 1 - *helper
>      };
> 
>    int main(void) {
>        return 0;
>      }

That one has the same problem as 

    int main(void) 
    {
        int x;  
        
        x - x;            
        return 0; 
    }


-- 
pete

[toc] | [prev] | [next] | [standalone]


#5419

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-04 02:02 -0500
Message-ID<iscl9q$dgc$1@dont-email.me>
In reply to#5373
On 6/3/2011 1:48 PM, pete wrote:
> Shao Miller wrote:
>
>> So let's please go on to:
>>
>>     char ** helper;
>>
>>     enum foo {
>>         bar = *helper + 1 - *helper
>>       };
>>
>>     int main(void) {
>>         return 0;
>>       }
>
> That one has the same problem as
>
>      int main(void)
>      {
>          int x;
>
>          x - x;
>          return 0;
>      }
>

In your example, 'x' is not initialized, and I agree that such is a 
concern.  In the example just above your example, 'helper' is at file 
scope[6.9.2p2].  What is the problem, exactly?

[toc] | [prev] | [next] | [standalone]


#5421

Frompete <pfiland@mindspring.com>
Date2011-06-04 06:49 -0400
Message-ID<4DEA0DB0.5BE6@mindspring.com>
In reply to#5419
Shao Miller wrote:
> 
> On 6/3/2011 1:48 PM, pete wrote:
> > Shao Miller wrote:
> >
> >> So let's please go on to:
> >>
> >>     char ** helper;
> >>
> >>     enum foo {
> >>         bar = *helper + 1 - *helper
> >>       };
> >>
> >>     int main(void) {
> >>         return 0;
> >>       }
> >
> > That one has the same problem as
> >
> >      int main(void)
> >      {
> >          int x;
> >
> >          x - x;
> >          return 0;
> >      }
> >
> 
> In your example, 'x' is not initialized, and I agree that such is a
> concern.  In the example just above your example, 'helper' is at file
> scope[6.9.2p2].  What is the problem, exactly?

I read it wrong. Sorry about that.

But, if (helper) is equal to NULL, 
which I believe is the case, 
then (*helper) is undefined.

But even if (*helper) was defined,
then (*helper + 1 - *helper) is still not a constant expression
and the compiler that I'm using, 
won't compile the above program.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#5428

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-04 09:32 -0500
Message-ID<isdfme$kvf$1@dont-email.me>
In reply to#5421
On 6/4/2011 5:49 AM, pete wrote:
> Shao Miller wrote:
>>
>> On 6/3/2011 1:48 PM, pete wrote:
>>> Shao Miller wrote:
>>>
>>>> So let's please go on to:
>>>>
>>>>      char ** helper;
>>>>
>>>>      enum foo {
>>>>          bar = *helper + 1 - *helper
>>>>        };
>>>>
>>>>      int main(void) {
>>>>          return 0;
>>>>        }
>>>
>>> That one has the same problem as
>>>
>>>       int main(void)
>>>       {
>>>           int x;
>>>
>>>           x - x;
>>>           return 0;
>>>       }
>>>
>>
>> In your example, 'x' is not initialized, and I agree that such is a
>> concern.  In the example just above your example, 'helper' is at file
>> scope[6.9.2p2].  What is the problem, exactly?
>
> I read it wrong. Sorry about that.
>

No problem.

> But, if (helper) is equal to NULL,
> which I believe is the case,
> then (*helper) is undefined.
>

I agree that the initially stored value for 'helper' would be comparable 
with 'NULL'.  I also agree that if '*helper' was evaluated while 
'helper' has a null pointer value, then there'd be undefined behaviour.

> But even if (*helper) was defined,
> then (*helper + 1 - *helper) is still not a constant expression
> and the compiler that I'm using,
> won't compile the above program.
>

May I ask which compiler, please?  Since I am concerned about 
portability, that'd be great to know.  Thanks!

[toc] | [prev] | [next] | [standalone]


#5436

Frompete <pfiland@mindspring.com>
Date2011-06-04 12:55 -0400
Message-ID<4DEA636F.7BF2@mindspring.com>
In reply to#5428
Shao Miller wrote:
> 
> On 6/4/2011 5:49 AM, pete wrote:
> > Shao Miller wrote:
> >>
> >> On 6/3/2011 1:48 PM, pete wrote:
> >>> Shao Miller wrote:
> >>>
> >>>> So let's please go on to:
> >>>>
> >>>>      char ** helper;
> >>>>
> >>>>      enum foo {
> >>>>          bar = *helper + 1 - *helper
> >>>>        };
> >>>>
> >>>>      int main(void) {
> >>>>          return 0;
> >>>>        }

> > But even if (*helper) was defined,
> > then (*helper + 1 - *helper) is still not a constant expression

I should have said 'not an "integral constant expression"'

> > and the compiler that I'm using,
> > won't compile the above program.
> >
> 
> May I ask which compiler, please?  Since I am concerned about
> portability, that'd be great to know.  Thanks!

One of the ancient ones.

Microsoft Developer Studio 97
VC++ 5.0 

Compiling...
new.c
C:\Program Files\DevStudio\SharedIDE\bin\new.c(5) : error C2057:
expected constant expression
Error executing cl.exe.

new.obj - 1 error(s), 0 warning(s)


-- 
pete

[toc] | [prev] | [next] | [standalone]


#5439

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-04 13:24 -0500
Message-ID<isdpom$i0p$1@dont-email.me>
In reply to#5436
On 6/4/2011 11:55 AM, pete wrote:
> Shao Miller wrote:
>>
>> On 6/4/2011 5:49 AM, pete wrote:
>>> Shao Miller wrote:
>>>>
>>>> On 6/3/2011 1:48 PM, pete wrote:
>>>>> Shao Miller wrote:
>>>>>
>>>>>> So let's please go on to:
>>>>>>
>>>>>>       char ** helper;
>>>>>>
>>>>>>       enum foo {
>>>>>>           bar = *helper + 1 - *helper
>>>>>>         };
>>>>>>
>>>>>>       int main(void) {
>>>>>>           return 0;
>>>>>>         }
>
>>> But even if (*helper) was defined,
>>> then (*helper + 1 - *helper) is still not a constant expression
>
> I should have said 'not an "integral constant expression"'
>

Ok.  I took that as your intended meaning, actually.

>>> and the compiler that I'm using,
>>> won't compile the above program.
>>>
>>
>> May I ask which compiler, please?  Since I am concerned about
>> portability, that'd be great to know.  Thanks!
>
> One of the ancient ones.
>
> Microsoft Developer Studio 97
> VC++ 5.0
>
> Compiling...
> new.c
> C:\Program Files\DevStudio\SharedIDE\bin\new.c(5) : error C2057:
> expected constant expression
> Error executing cl.exe.
>
> new.obj - 1 error(s), 0 warning(s)
>

Do you suppose it's compiling according to some C Standard, or is it 
compiling as C++?

Also, if it's not a complete waste of your time, how does it react to:

   int x;

   enum foo {
       bar = 1 ? 3 : x - x
     };

   int main(void) {
       return 0;
     }

?

[toc] | [prev] | [next] | [standalone]


#5442

Frompete <pfiland@mindspring.com>
Date2011-06-04 14:56 -0400
Message-ID<4DEA7FEE.5C72@mindspring.com>
In reply to#5439
Shao Miller wrote:
> 
> On 6/4/2011 11:55 AM, pete wrote:
> > Shao Miller wrote:
> >>
> >> On 6/4/2011 5:49 AM, pete wrote:
> >>> Shao Miller wrote:
> >>>>
> >>>> On 6/3/2011 1:48 PM, pete wrote:
> >>>>> Shao Miller wrote:
> >>>>>
> >>>>>> So let's please go on to:
> >>>>>>
> >>>>>>       char ** helper;
> >>>>>>
> >>>>>>       enum foo {
> >>>>>>           bar = *helper + 1 - *helper
> >>>>>>         };
> >>>>>>
> >>>>>>       int main(void) {
> >>>>>>           return 0;
> >>>>>>         }
> >
> >>> But even if (*helper) was defined,
> >>> then (*helper + 1 - *helper) is still not a constant expression
> >
> > I should have said 'not an "integral constant expression"'
> >
> 
> Ok.  I took that as your intended meaning, actually.
> 
> >>> and the compiler that I'm using,
> >>> won't compile the above program.
> >>>
> >>
> >> May I ask which compiler, please?  Since I am concerned about
> >> portability, that'd be great to know.  Thanks!
> >
> > One of the ancient ones.
> >
> > Microsoft Developer Studio 97
> > VC++ 5.0
> >
> > Compiling...
> > new.c
> > C:\Program Files\DevStudio\SharedIDE\bin\new.c(5) : error C2057:
> > expected constant expression
> > Error executing cl.exe.
> >
> > new.obj - 1 error(s), 0 warning(s)
> >
> 
> Do you suppose it's compiling according to some C Standard, or is it
> compiling as C++?

It's Microsoft's 1997 attempt at C89.
It compiles as c++ only when the file name is *.cpp

> Also, if it's not a complete waste of your time, how does it react to:
> 
>    int x;
> 
>    enum foo {
>        bar = 1 ? 3 : x - x
>      };
> 
>    int main(void) {
>        return 0;
>      }
> 
> ?

The compiler likes that one.
If the (1) is replaced with a zero, then it doesn't like it.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#5443

Frompete <pfiland@mindspring.com>
Date2011-06-04 15:38 -0400
Message-ID<4DEA89A8.47C0@mindspring.com>
In reply to#5442
pete wrote:
> 
> Shao Miller wrote:

> >
> >    int x;
> >
> >    enum foo {
> >        bar = 1 ? 3 : x - x
> >      };
> >
> >    int main(void) {
> >        return 0;
> >      }
> >
> > ?
> 
> The compiler likes that one.
> If the (1) is replaced with a zero, then it doesn't like it.

Here's one that I like:

/* BEGIN new.c */

#include <stdio.h>

int main(void) 
{
    char array[][1 + sizeof (void*)] = {0};
    enum foo {
        bar = sizeof *(1 ? 0 : array)
    };

    printf("bar is %u\n", (unsigned)bar);
    return 0;
}

/* END new.c */


-- 
pete

[toc] | [prev] | [next] | [standalone]


#5450

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-04 18:25 -0500
Message-ID<isebdi$rve$1@dont-email.me>
In reply to#5443
On 6/4/2011 2:38 PM, pete wrote:
> pete wrote:
>>
>> Shao Miller wrote:
>
>>>
>>>     int x;
>>>
>>>     enum foo {
>>>         bar = 1 ? 3 : x - x
>>>       };
>>>
>>>     int main(void) {
>>>         return 0;
>>>       }
>>>
>>> ?
>>
>> The compiler likes that one.
>> If the (1) is replaced with a zero, then it doesn't like it.
>

Hee hee hee.

> Here's one that I like:
>
> /* BEGIN new.c */
>
> #include<stdio.h>
>
> int main(void)
> {
>      char array[][1 + sizeof (void*)] = {0};
>      enum foo {
>          bar = sizeof *(1 ? 0 : array)
>      };
>
>      printf("bar is %u\n", (unsigned)bar);
>      return 0;
> }
>
> /* END new.c */
>

Compiling with GCC, the compiler complained to me that there were 
missing braces around the initializer.  When I used:

   char array[][1 + sizeof (void*)] = {{0}};

it liked that better.

So if I understand your code correctly, 'array' "decays" from:

   char[1][1 + sizeof (void *)]

to:

   char(*)[1 + sizeof (void *)]

and then the null pointer constant '0' is converted to a null pointer 
with type 'char(*)[1 + sizeof (void *)]'.  And then the unary 
indirection operator '*' is applied to that and is a subexpression with 
type 'char[1 + sizeof (void *)]'.  The 'sizeof' is then applied to that 
and ought to yield '1 + sizeof (void *)' as the value for 'bar'.

This seems to allow for using 'array' to produce an integer constant 
expression, even though:
- It will not yield an address constant if evaluated.
- It is not evaluated.
- 6.6p6 suggests some restrictions on operands, and 'array' is an 
operand [of a subexpression] that doesn't seem to match those restrictions.

Very nice. :)

[toc] | [prev] | [next] | [standalone]


#5478

Frompete <pfiland@mindspring.com>
Date2011-06-05 07:10 -0400
Message-ID<4DEB6410.410F@mindspring.com>
In reply to#5450
Shao Miller wrote:
> 
> On 6/4/2011 2:38 PM, pete wrote:
> > pete wrote:

> >      char array[][1 + sizeof (void*)] = {0};

> Compiling with GCC, the compiler complained to me that there were
> missing braces around the initializer.  When I used:
> 
>    char array[][1 + sizeof (void*)] = {{0}};
> 
> it liked that better.

Thank you.
I think I meant to write

    char array[1][1 + sizeof (void*)] = {0};

instead.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#5381

FromHarald van Dijk <truedfx@gmail.com>
Date2011-06-03 13:39 -0700
Message-ID<aa0e29e7-b583-4369-af8a-e6d800bf94c3@p13g2000yqh.googlegroups.com>
In reply to#5368
On Jun 3, 7:57 pm, Shao Miller <sha0.mil...@gmail.com> 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?

Yes.

6.6p6:
An integer constant expression shall have integer type and shall only
have operands
that are integer constants, enumeration constants, character
constants, sizeof
expressions whose results are integer constants, and floating
constants that are the
immediate operands of casts. Cast operators in an integer constant
expression shall only
convert arithmetic types to integer types, except as part of an
operand to the sizeof
operator.

Address constants are not permitted in integer constant expressions.
This is not a constraint, so a compiler is free to accept it without
any notice, but the behaviour is undefined.

[toc] | [prev] | [next] | [standalone]


#5411

FromTim Rentsch <txr@alumni.caltech.edu>
Date2011-06-03 19:58 -0700
Message-ID<kfnwrh2uwt5.fsf@x-alumni2.alumni.caltech.edu>
In reply to#5381
Harald van Dijk <truedfx@gmail.com> writes:

> On Jun 3, 7:57 pm, Shao Miller <sha0.mil...@gmail.com> 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?
>
> Yes.
>
> 6.6p6:
> An integer constant expression shall have integer type and shall only
> have operands
> that are integer constants, enumeration constants, character
> constants, sizeof
> expressions whose results are integer constants, and floating
> constants that are the
> immediate operands of casts. Cast operators in an integer constant
> expression shall only
> convert arithmetic types to integer types, except as part of an
> operand to the sizeof
> operator.
>
> Address constants are not permitted in integer constant expressions.

Not exactly.  Implementations are allowed to accept address
constants in integer constant expressions under 6.6p10.  In
such an implementation the behavior is defined, not undefined.
The code is conforming, just not strictly conforming.

> This is not a constraint, so a compiler is free to accept it without
> any notice, but the behaviour is undefined.

If the implementation does not accept address constants in
integer constant expressions, then the definition for 'bar'
fails to be an integer constant expression, which is a
constraint violation and a diagnostic must be issued.

[toc] | [prev] | [next] | [standalone]


#5420

FromHarald van Dijk <truedfx@gmail.com>
Date2011-06-04 01:57 -0700
Message-ID<e706903b-5ab3-4f2c-ac37-7d5f08841a74@r17g2000yqc.googlegroups.com>
In reply to#5411
On Jun 4, 4:58 am, Tim Rentsch <t...@alumni.caltech.edu> wrote:
> Harald van Dijk <true...@gmail.com> writes:
> > On Jun 3, 7:57 pm, Shao Miller <sha0.mil...@gmail.com> wrote:
> >>    int helper[2];
>
> >>    enum foo {
> >>        bar = helper + 1 - helper
> >>      };
>
> >> Does that code include any undefined behaviour?
>
> > Yes.
>[snip]
> > Address constants are not permitted in integer constant expressions.
>
> Not exactly.  Implementations are allowed to accept address
> constants in integer constant expressions under 6.6p10.  In
> such an implementation the behavior is defined, not undefined.
> The code is conforming, just not strictly conforming.
>
> > This is not a constraint, so a compiler is free to accept it without
> > any notice, but the behaviour is undefined.
>
> If the implementation does not accept address constants in
> integer constant expressions, then the definition for 'bar'
> fails to be an integer constant expression, which is a
> constraint violation and a diagnostic must be issued.

You're right, I missed the italics in 6.6p6: it defines the term
"integer constant expression", meaning any violation of a "shall"
means the expression is not an integer constant expression, and that
"integer constant expression" does not simply mean "constant
expression of integer type". However, while 6.6p10 grants permission
to accept other forms of constant expressions, I do not see it
altering the definition of 6.6p6. An implementation that accepts
"helper + 1 - helper" as a constant expression under 6.6p10 cannot
accept it as an integer constant expression. It is a constant
expression of integer type, which is not the same thing when 6.6p6
defines i.c.e. differently. Which means that, on such an
implementation, it is acceptable as an initialiser at file scope, but
not as an enumeration constant.

I don't think any implementation behaves this way, so either I'm
missing something, or the standard is.

[toc] | [prev] | [next] | [standalone]


#5422

FromTim Rentsch <txr@alumni.caltech.edu>
Date2011-06-04 05:22 -0700
Message-ID<kfn4o45vlab.fsf@x-alumni2.alumni.caltech.edu>
In reply to#5420
Harald van Dijk <truedfx@gmail.com> writes:

> On Jun 4, 4:58 am, Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> Harald van Dijk <true...@gmail.com> writes:
>> > On Jun 3, 7:57 pm, Shao Miller <sha0.mil...@gmail.com> wrote:
>> >>    int helper[2];
>>
>> >>    enum foo {
>> >>        bar = helper + 1 - helper
>> >>      };
>>
>> >> Does that code include any undefined behaviour?
>>
>> > Yes.
>>[snip]
>> > Address constants are not permitted in integer constant expressions.
>>
>> Not exactly.  Implementations are allowed to accept address
>> constants in integer constant expressions under 6.6p10.  In
>> such an implementation the behavior is defined, not undefined.
>> The code is conforming, just not strictly conforming.
>>
>> > This is not a constraint, so a compiler is free to accept it without
>> > any notice, but the behaviour is undefined.
>>
>> If the implementation does not accept address constants in
>> integer constant expressions, then the definition for 'bar'
>> fails to be an integer constant expression, which is a
>> constraint violation and a diagnostic must be issued.
>
> You're right, I missed the italics in 6.6p6: it defines the term
> "integer constant expression", meaning any violation of a "shall"
> means the expression is not an integer constant expression, and that
> "integer constant expression" does not simply mean "constant
> expression of integer type". However, while 6.6p10 grants permission
> to accept other forms of constant expressions, I do not see it
> altering the definition of 6.6p6.

6.6p10 allows 'other forms of constant expressions' plural, which
also includes the different subcategories of constant expression.
One reason for doing this is so implementations can define things
like the 'offsetof' macro using an ordinary expression and still
have that expression be an integer constant expression.

Also, if you look at the description of 'constant expression' (as
opposed to the subcategories) all the restrictions on it are
either syntactic or constraints.  Violating either of those would
necessitate a diagnostic message, in which case 6.6p10 would
serve no purpose, since the same result could be achieved by just
defining an extension.

> An implementation that accepts
> "helper + 1 - helper" as a constant expression under 6.6p10 cannot
> accept it as an integer constant expression. It is a constant
> expression of integer type, which is not the same thing when 6.6p6
> defines i.c.e. differently. Which means that, on such an
> implementation, it is acceptable as an initialiser at file scope, but
> not as an enumeration constant.

If 6.6p10 applied only to constant expressions and not to integer
constant expressions what you say would be right, but 6.6p10 also
is meant to allow (and does allow, as I read it) implementations
to accept other forms of integer constant expressions (or address
constants, etc).


> I don't think any implementation behaves this way, so either I'm
> missing something, or the standard is.

Have you tried   gcc -ansi -pedantic  ?

[toc] | [prev] | [next] | [standalone]


#5438

FromHarald van Dijk <truedfx@gmail.com>
Date2011-06-04 10:16 -0700
Message-ID<f55a1046-300b-4197-8f71-abc65e16e97a@16g2000yqy.googlegroups.com>
In reply to#5422
On Jun 4, 2:22 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
> 6.6p10 allows 'other forms of constant expressions' plural,

It would be plural both with your interpretation as with mine.

> which
> also includes the different subcategories of constant expression.

It doesn't say that in the standard, though I was already agreeing
that that seems to be what is intended. This would clearly not be the
intended interpretation for something like "signed integer types",
though: permission to extend the definition of "signed integer type"
should not implicitly allow implementations to extend the definition
of "standard signed integer type".[*] Without explicit permission to
redefine "integer constant expression", an implementer does not have
that luxury either.

> One reason for doing this is so implementations can define things
> like the 'offsetof' macro using an ordinary expression and still
> have that expression be an integer constant expression.

I know, I've actually had the opportunity to modify one compiler to
accept extended forms of integer constant expressions: it was so
strict, that it was impossible to define offsetof as an i.c.e., even
though it was more than capable of simplifying the common forms of
offsetof at translation time. FWIW, I opted for a "literal" keyword to
mark the following expression as an extended constant expression, so
that you could do:

typedef char __char;
typedef size_t __size_t;
#pragma keyword __offsetof_magic for keyword literal
#define offsetof(s, m) (__offsetof_magic (__size_t) ((__char *) &((s
*) 0)->m - (__char *) 0))

-- please excuse possible typos -- which resulted in errors at a later
stage if the expression was too complex to simplify.

> Also, if you look at the description of 'constant expression' (as
> opposed to the subcategories) all the restrictions on it are
> either syntactic or constraints.  Violating either of those would
> necessitate a diagnostic message, in which case 6.6p10 would
> serve no purpose, since the same result could be achieved by just
> defining an extension.

6.6p10 would allow

char p[2];
int i = (int) p;

as an extension, because it would violate none of the relevant
"shall"s in 6.6: (int) p would be a constant expression of type int,
without being an integer constant expression. 6.7.8p4 requires a
constant expression, so without 6.6p10, it would be a constraint
violation.

> If 6.6p10 applied only to constant expressions and not to integer
> constant expressions what you say would be right, but 6.6p10 also
> is meant to allow (and does allow, as I read it) implementations
> to accept other forms of integer constant expressions (or address
> constants, etc).

It is only on the "and does allow" that we disagreee.

> > I don't think any implementation behaves this way, so either I'm
> > missing something, or the standard is.
>
> Have you tried   gcc -ansi -pedantic  ?

Yes. Do you know of any constant expression of integer type that is
accepted in file scope initialisers, but not in enumeration constants?
Because I don't. Older versions of gcc accepted many extended forms of
constant expressions in both contexts, current versions accept few if
any in either context.

[*] The "signed integer types" section is worded much better, and
clearly only allows implementation-defined "extended signed integer
types". I'm wondering how we would interpret the standard if it said

"There are five /standard signed integer types/, designated as signed
char, short
 int, int, long int, and long long int. (These and other types may be
designated
 in several additional ways, as described in 6.7.2.) There may also be
other
 implementation-defined signed integer types."

[toc] | [prev] | [next] | [standalone]


#5468

FromTim Rentsch <txr@alumni.caltech.edu>
Date2011-06-04 23:03 -0700
Message-ID<kfntyc4u85q.fsf@x-alumni2.alumni.caltech.edu>
In reply to#5438
Harald van Dijk<truedfx@gmail.com> writes:

> On Jun 4, 2:22 pm, Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> 6.6p10 allows 'other forms of constant expressions' plural,
>
> It would be plural both with your interpretation as with mine.

Actually singular is more usual if only the one category is
meant.  Try it with 'function definition' - 'other forms of
function definition', not 'other forms of function definitions'.


>> which
>> also includes the different subcategories of constant expression.
>
> It doesn't say that in the standard,

There's no disagreement about what words appear, but the question
is what elements are included under those words.  For example, a
statement in the Standard might use the term 'declarations' but
would also apply to 'definitions', as (many) definitions are also
declarations.  Inferring that a statement about 'declarations'
doesn't also apply to those 'definitions' just because the word
'definitions' isn't mentioned locally is obviously wrong-headed.

> though I was already agreeing
> that that seems to be what is intended. This would clearly not be the
> intended interpretation for something like "signed integer types",
> though: permission to extend the definition of "signed integer type"
> should not implicitly allow implementations to extend the definition
> of "standard signed integer type".[*]

This analogy seems too hypothetical and not closely analogous
enough to be relevant to the current discussion.

> Without explicit permission to
> redefine "integer constant expression", an implementer does not have
> that luxury either.

You say this like it's an article of faith, but generally the
reverse is true:  any statement about a broad category of items
also applies to more specialized subcategories unless a specific
exception is called out, like the 'declaration' and 'definition'
example above.  For example, the Standard includes this text:
"Thus, * can be used only in function declarations that are not
definitions (see 6.7.5.3)."  Unless you can cite some other
example passages from the Standard that support the "Without
explicit permission" theory, I don't see any reason to assume
it applies here.


>> One reason for doing this is so implementations can define things
>> like the 'offsetof' macro using an ordinary expression and still
>> have that expression be an integer constant expression.
>
> I know, I've actually had the opportunity to modify one compiler to
> accept extended forms of integer constant expressions: it was so
> strict, that it was impossible to define offsetof as an i.c.e., even
> though it was more than capable of simplifying the common forms of
> offsetof at translation time. FWIW, I opted for a "literal" keyword to
> mark the following expression as an extended constant expression, so
> that you could do:
>
> typedef char __char;
> typedef size_t __size_t;
> #pragma keyword __offsetof_magic for keyword literal
> #define offsetof(s, m) (__offsetof_magic (__size_t) ((__char *) &((s
> *) 0)->m - (__char *) 0))
>
> -- please excuse possible typos -- which resulted in errors at a later
> stage if the expression was too complex to simplify.

One point of 6.6p10 is that such goofiness is not necessary.

(I hasten to add that the 'goofiness' I'm talking about
here is not your design choice but the circumlocutions
needed if other forms of ICE's were not available under
6.6p10.  The definitions above could be a perfectly
reasonable design choice even if the circumlocutions
were not necessary.)


>> Also, if you look at the description of 'constant expression' (as
>> opposed to the subcategories) all the restrictions on it are
>> either syntactic or constraints.  Violating either of those would
>> necessitate a diagnostic message, in which case 6.6p10 would
>> serve no purpose, since the same result could be achieved by just
>> defining an extension.
>
> 6.6p10 would allow
>
> char p[2];
> int i = (int) p;
>
> as an extension, because it would violate none of the relevant
> "shall"s in 6.6: (int) p would be a constant expression of type int,
> without being an integer constant expression. 6.7.8p4 requires a
> constant expression, so without 6.6p10, it would be a constraint
> violation.

No, 6.6p10 is not necessary for this.  The expression '(int) p'
(provided it can be evaluated during translation) already qualifies
as a constant expression.  The discussion in 3p1 and 6.1p1 make it
clear that the term "constant expression" is defined syntactically,
and '(int) p' already meets this definition.  The "shall"s in 6.6p3,
6.6p4, and 6.6p7 (and following) are not part of the definition of
"constant expression".  Failure to meet the "shall"s in 6.6p3 or
6.6p4 would require a diagnostic if a constant expression were
needed, but not meeting the "shall"s in 6.6p7 (and following) would
only be undefined behavior, not a constraint violation, and the
expression in question would still be a constant expression (provided
6.6p1 and 6.6p2 are satisfied) - no diagnostic required.

One could argue that 6.6p7 is defining a new category, "constant
expressions in initializers", but then under your theory 6.6p10
wouldn't apply to those either since it doesn't name them explicitly.


>> If 6.6p10 applied only to constant expressions and not to integer
>> constant expressions what you say would be right, but 6.6p10 also
>> is meant to allow (and does allow, as I read it) implementations
>> to accept other forms of integer constant expressions (or address
>> constants, etc).
>
> It is only on the "and does allow" that we disagreee.

If you think 6.6p10 is _meant_ to allow other forms of ICE, but
_doesn't_ allow other forms of ICE, does this mean you think
how you read the Standard differs from how the committee
reads the Standard?


>> > I don't think any implementation behaves this way, so either I'm
>> > missing something, or the standard is.
>>
>> Have you tried   gcc -ansi -pedantic  ?
>
> Yes. Do you know of any constant expression of integer type that is
> accepted in file scope initialisers, but not in enumeration constants?
> Because I don't.

Yes.  One version of gcc I use accepts

    char x[1];
    static long xlong = (long) x;

but doesn't accept '(long) x' as an integer constant expression.
(The expression '(long) x' has type 'long' rather than type 'int',
which may perforce disqualify it for enumeration constants, but it
also doesn't qualify as "just" an integer constant expression, where
which particular value it has doesn't matter as long as the type is
integral.)  [The pun in the last sentence was not intentional!]

> Older versions of gcc accepted many extended forms of
> constant expressions in both contexts, current versions accept few if
> any in either context.

I don't draw any conclusions from this other than that recently a
different decision was made about which forms to include (by
default?) in the conforming modes.  Even what you're calling the
"older versions" of gcc have been around long enough so questions
about conformance should have been previously addressed;  IIANM
the wording of 6.6p10 is unchanged since C90 (except of course
the section numbering was different).


> [*] The "signed integer types" section is worded much better, and
> clearly only allows implementation-defined "extended signed integer
> types". I'm wondering how we would interpret the standard if it said
>
> "There are five /standard signed integer types/, designated as signed
> char, short
>  int, int, long int, and long long int. (These and other types may be
> designated
>  in several additional ways, as described in 6.7.2.) There may also be
> other
>  implementation-defined signed integer types."

Seems like sort of a strawman.  I expect this wording would be
judged defective because it doesn't define the term 'signed
integer types', not to mention the term 'extended signed integer
types' which is used several times in other places in the
Standard.

[toc] | [prev] | [next] | [standalone]


Page 1 of 3  [1] 2 3  Next page →

Back to top | Article view | comp.lang.c


csiph-web