Sender: Martin WeckerHello Linus,
Date: Tue, 20 Mar 2018 22:13:35 +0000
Topic: Detecting Integer Constant Expressions in a Macro
__builtin_choose_expr
, and looks like this: #define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
x
itself is not calculated in gcc , although this is not guaranteed by the standard (I did not check this fact in older versions of gcc .)Sender: Linus Torvalds <>
Date: Tue, 20 Mar 2018 16:08:30 -0700
Subject: Re: Detection of integer constant expressions in a macro
On Tue, Mar 20, 2018 at 3:13 PM, Martin WeckerNo, this is not an "idea."
<Martin.Uecker@med.uni-goettingen.de> wrote:
I have an idea:
The test for integer constant expressions, which returns the integer constant expression itself, which should be suitable for transmission in __builtin_choose_expr, and looks like this:OK, here I see that
#define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
(void *)((x)*0l))
becomes NULL
when x
is ICE
. Good. With a constant, we have: sizeof( 1 ? NULL : (int *) 1)
NULL
, then its end result is a different type (int *)
.sizeof(int)
.NULL
.NULL
, are different - so now it returns "void *"
.(sizeof(*(void *)(x))
, which in gcc is usually different from int ."sizeof(*(void *)1)"
not necessarily strictly defined. For gcc it is 1. This can cause warnings ( warnings ).By the way, in this expression, x
itself is not calculated in gcc , although this is not guaranteed by the standard (I did not check it in older versions of gcc .)
Oh, as for me, by the standard, it is guaranteed that the sizeof()
operator does not calculate the value of the argument, only its type. #define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
ICE_P(x)
. P
is a lispovy predicate according to the rules of naming. ICE stands for integer constant expression. We want to return true
if x
is an integer constant expression, and false
otherwise.true
if the right side of the comparison is equal to sizeof(int)
. Let's try to deploy it. sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))
1 ? ((void*)((x) * 0l)) : (int*)1
true
. As Linus explains, when x
is ICE, the left side becomes NULL
. So, we have two possible options:x
ICE: 1 ? ((void*)(NULL)) : (int*)1
1 ? ((void*)(NULL)) : (int*)1
x
not ICE: 1 ? ((void*)(NOT-NULL)) : (int*)1
1 ? ((void*)(NOT-NULL)) : (int*)1
void*
on the left is NULL
or not.NULL
(x is ICE), the expression returns type int*
NULL
(x is not ICE), the expression returns void*
NULL void *
into int *
, but when void *
is not NULL
, it turns int *
void *
instead. Now we can return to the original expression, and we get the following:x
is ICE: sizeof(int) == sizeof(*(int *))
x
is not ICE: sizeof(int) == sizeof(*(void *))
sizeof(*(void *))
is 1.icep.c
: /* : gcc icep.c -o icep && ./icep : $ gcc icep.c -o icep && ./icep ICE_P(1): 1 ICE_P('c'): 1 ICE_P(rand()): 0 */ #include <stdio.h> #include <stdlib.h> #define ICE_P(x) (sizeof(int) == sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1))) #define CHECK(x) printf("ICE_P(%s): %d\n", #x, ICE_P(x)) int main() { CHECK(1); CHECK('c'); CHECK(rand()); return 0; }
x * 0
. If x
is an integer constant, the compiler can perform a calculation, and the integer by zero is zero. If x
is not an integer constant, then the compiler cannot perform this computation, and it is unknown whether it is zero. This result is cast to an “empty” pointer ( void pointer ). This is how we know if NULL
or not (since the void pointer to zero is the definition of NULL
).a ? b : c
a ? b : c
. It is clear that b
and c
can have different types, and in this case, the compiler must figure out the “common” type of these expressions. Here c
is clearly a pointer to an int
. But NULL
compatible with other types of pointers. So if b
is NULL
, then the generic type is int*
, since it describes both expressions. However, if it is not statically known whether b NULL
, then the only type that matches void*
and int*
is void*
.sizeof(*(void*))
, when x
is not an integer constant expression, and sizeof(*(int*))
, when x
is it itself.Source: https://habr.com/ru/post/352322/
All Articles