Variably modified at file scope due to (void *)0 == (sem_t *)0?

Liu Hao lh_mouse@126.com
Thu Oct 4 12:28:00 GMT 2018


在 2018-10-04 17:11, Sebastian Huber 写道:
> On 04/10/2018 10:56, Jonathan Wakely wrote:
>> On Thu, 4 Oct 2018 at 09:51, Sebastian Huber wrote:
>>> Hello,
>>>
>>> I use a typedef for static assertions for pre C11 compilers. For one
>>> static assertion
>>>
>>> typedef struct { int i; } sem_t;
>>>
>>> typedef int static_assert_sem_failed [((void *)0 == (sem_t *)0) ? 1 : 
>>> -1];
>>>
>>> _Static_assert((void *)0 == (sem_t *)0, "sem_failed");
>>>
>>> I get a warning like this:
>>>
>>> gcc -S -o - sa.c > /dev/null
>>> sa.c:3:1: warning: variably modified ‘static_assert_sem_failed’ at file
>>> scope
>>>    typedef int static_assert_sem_failed [((void *)0 == (sem_t *)0) ? 
>>> 1 : -1];
>>>    ^~~~~~~
>>>
>>> Is there some way to get around this warning?
>> You could move the homemade assertion so it's not at file scope:
>>
>> __attribute__((used)) static void assertions() {
>>    __attribute__((used)) typedef int static_assert_sem_failed [((void
>> *)0 == (sem_t *)0) ? 1 : -1];
>> }
> 
> Thanks, this works.
> 

This works for me on GCC 4.9, 7 and 8:

```
#define FORCE_CONSTANT_TRUE(expr)  (__builtin_constant_p(expr) ? (expr) : 0)

typedef int static_assert_sem_failed [FORCE_CONSTANT_TRUE((void *)0 == 
(sem_t *)0) ? 1 : -1];
```

>>
>>> The same expression in the
>>> _Static_assert() doen't lead to a warning.
>> It does with -pedantic, and that makes the reason for the warning 
>> clearer:
>>
>> foo.c:5:26: warning: expression in static assertion is not an integer
>> constant expression [-Wpedantic]
>>   _Static_assert((void *)0 == (sem_t *)0, "sem_failed");
> 
> This looks bad, so basically a pointer constant doesn't exist in 
> standard C?
> 

As a difference from C++, C does not allow pointer operands in an 
/integer constant expression/, despite the type of results of pointer 
comparison, which is `int`.

Because of VLAs, it is discouraged to use array extents for such 
purpose. You may prefer bitfield widths, which would result in a better 
message:

```
struct static_assert_sem_failed
   { int unused : ((void *)0 == (sem_t *)0) ? 1 : -1; };

/*
lh_mouse@lhmouse-ideapad ~/Desktop $ gcc test.5.c  -Wall -Wextra 
-Wpedantic -Werror
test.5.c:4:9: error: bit-field ‘unused’ width not an integer constant 
expression [-Werror=pedantic]
    { int unused : ((void *)0 == (sem_t *)0) ? 1 : -1; };
*/
```


-- 
Best regards,
LH_Mouse



More information about the Gcc-help mailing list