_Generic 表达式中指向 VLA 类型控制表达式的指针
A pointer-to-a-VLA-typed controlling expression in a _Generic expression
为什么这个静态断言不会在主要编译器上触发?
void test(int x){
_Static_assert(_Generic( (char(*)[x])0,
char (*)[1]: 1, default: 0),"");
}
https://gcc.godbolt.org/z/E67a79oPT
指向可变长度数组的指针应该与指向固定长度数组的指针兼容吗?
它们是兼容的。 C 2018 6.7.6.2 6 说“对于要兼容的两种数组类型,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且是整数常量表达式,则两个大小说明符应具有相同的常量值......”因为两个大小说明符都是整数常量表达式是不正确的,具有相同值的要求不适用。
指针兼容性继承自 pointed-to 类型。
它们实际上是兼容的。
首先,C standard 的第 6.7.6.2p6 节说明了以下关于数组类型兼容性的内容:
For two array types to be compatible, both shall have compatible
element types, and if both size specifiers are present, and are
integer constant expressions, then both size specifiers shall have the
same constant value. If the two array types are used in a context
which requires them to be compatible, it is undefined behavior if the
two size specifiers evaluate to unequal values.
由此,有一个要求,如果两个数组大小都是整数常量表达式(即都不是 VLA),那么它们必须相同。但是,如果一个是 VLA,则这不适用,因此它们兼容。
此外,第 6.2.7p3 节关于复合类型的说明如下:
A composite type can be constructed from two types that are
compatible; it is a type that is compatible with both of the two types
and satisfies the following conditions:
- If both types are array types, the following rules are applied:
- If one type is an array of known constant size, the composite type is an array of that size.
- Otherwise, if one type is a variable length array whose size is specified by an expression that is not evaluated, the behavior is
undefined.
- Otherwise, if one type is a variable length array whose size is specified, the composite type is a variable length array of that size.
- Otherwise, if one type is a variable length array of unspecified size, the composite type is a variable length array of unspecified
size.
- Otherwise, both types are arrays of unknown size and the composite type is an array of unknown size. The element type of the composite
type is the composite type of the two element types.
这意味着当比较类型char(*)[x]
和char(*)[1]
时,它们的复合类型是char(*)[1]
。这也意味着 char(*)[x]
与指向 char
的固定大小数组的 任何 指针兼容。因此,如果您的函数如下所示:
void test(int x){
_Static_assert(_Generic( (char(*)[x])0,
char (*)[2]: 2,
char (*)[1]: 1,
default: 0),"");
}
您会遇到编译错误,因为控制表达式与多个选项兼容,即使这些选项彼此不兼容。
为什么这个静态断言不会在主要编译器上触发?
void test(int x){
_Static_assert(_Generic( (char(*)[x])0,
char (*)[1]: 1, default: 0),"");
}
https://gcc.godbolt.org/z/E67a79oPT
指向可变长度数组的指针应该与指向固定长度数组的指针兼容吗?
它们是兼容的。 C 2018 6.7.6.2 6 说“对于要兼容的两种数组类型,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且是整数常量表达式,则两个大小说明符应具有相同的常量值......”因为两个大小说明符都是整数常量表达式是不正确的,具有相同值的要求不适用。
指针兼容性继承自 pointed-to 类型。
它们实际上是兼容的。
首先,C standard 的第 6.7.6.2p6 节说明了以下关于数组类型兼容性的内容:
For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.
由此,有一个要求,如果两个数组大小都是整数常量表达式(即都不是 VLA),那么它们必须相同。但是,如果一个是 VLA,则这不适用,因此它们兼容。
此外,第 6.2.7p3 节关于复合类型的说明如下:
A composite type can be constructed from two types that are compatible; it is a type that is compatible with both of the two types and satisfies the following conditions:
- If both types are array types, the following rules are applied:
- If one type is an array of known constant size, the composite type is an array of that size.
- Otherwise, if one type is a variable length array whose size is specified by an expression that is not evaluated, the behavior is undefined.
- Otherwise, if one type is a variable length array whose size is specified, the composite type is a variable length array of that size.
- Otherwise, if one type is a variable length array of unspecified size, the composite type is a variable length array of unspecified size.
- Otherwise, both types are arrays of unknown size and the composite type is an array of unknown size. The element type of the composite type is the composite type of the two element types.
这意味着当比较类型char(*)[x]
和char(*)[1]
时,它们的复合类型是char(*)[1]
。这也意味着 char(*)[x]
与指向 char
的固定大小数组的 任何 指针兼容。因此,如果您的函数如下所示:
void test(int x){
_Static_assert(_Generic( (char(*)[x])0,
char (*)[2]: 2,
char (*)[1]: 1,
default: 0),"");
}
您会遇到编译错误,因为控制表达式与多个选项兼容,即使这些选项彼此不兼容。