`const` 限定类型可以出现在 C99 程序中的什么地方
Where can `const` qualified types occur in C99 programs
TL;DR const
在C99程序中哪里可以出现而不被忽略?或者相反:在 C99 程序中 const
添加重要约束的位置?
我的理解是 const
限定符仅在少数允许限定类型的地方有用。 "Useful"这里用的是语义,意思是"adding non-trivial constraints"。 const
有用的地方列表包括:
- 附加到指针和数组类型来描述指向/元素类型的可变性。例如。
int const *
- 描述一些变量声明的可变性(作为函数参数或局部变量)。例如。
int const x = 1
- 描述
struct
/union
中某些字段的可变性。例如。 struct Foo { int baz; int const quux; }
- 在
typedef
中,当它们用于上述情况之一时
- ???
我很难得到一份详尽的清单。我已经浏览了 C99 规范,但这很难读懂。 :)
非常感谢帮助!
编辑
以下是 AFAICT const
不是 "useful" 的一些情况:
- 任意 return 值(右值不能改变)。例如。
const int foo() { return 2; }
- 任意类型转换(仍然是右值...)。例如。
(int const) bar()
sizeof
(qualified/unqualified 类型的对齐方式和大小相同)。例如。 sizeof(const int)
根据语言语法,type-qualifier 可以作为 type-name 的一部分出现。如果您查看 type-name 的语言语法,您会发现可以使用它的所有上下文。那将是:声明、转换、复合文字、泛型、sizeof
、_Atomic
、_Alignas
、_Alignof
.
可以肯定地说,在最后四个的上下文中 - sizeof
、_Atomic
、_Alignas
、_Alignof
- const
在任何间接级别上都没有区别。
_Generic
似乎仍未指定,但可以安全地假设顶级 const
在那里没有区别。在更深层次的间接性中,const
在 _Generic
.
中很重要
至于其他,管理规则是:顶级 const
仅对 lvalues 有意义。应用于 rvalues 时没有区别。这意味着将顶级 const 限定应用于函数 return 类型或强制转换中的目标类型是没有意义的。
在更深层次的间接寻址中使用的限定词,显然很重要。
请注意,复合文字是左值,这意味着复合文字中的顶级 const
很重要
int *p = (const struct { int a[10]; }) { 0 }.a; // Error: discards `const`
一些奇怪的例子仍然存在,例如
const struct S { int a[10]; } foo(void)
{
return (struct S) { 0 };
}
int main()
{
int *p = foo().a;
}
它在 GCC 中编译,但是,如果我没记错的话,行为无论如何都是未定义的。
TL;DR const
在C99程序中哪里可以出现而不被忽略?或者相反:在 C99 程序中 const
添加重要约束的位置?
我的理解是 const
限定符仅在少数允许限定类型的地方有用。 "Useful"这里用的是语义,意思是"adding non-trivial constraints"。 const
有用的地方列表包括:
- 附加到指针和数组类型来描述指向/元素类型的可变性。例如。
int const *
- 描述一些变量声明的可变性(作为函数参数或局部变量)。例如。
int const x = 1
- 描述
struct
/union
中某些字段的可变性。例如。struct Foo { int baz; int const quux; }
- 在
typedef
中,当它们用于上述情况之一时 - ???
我很难得到一份详尽的清单。我已经浏览了 C99 规范,但这很难读懂。 :)
非常感谢帮助!
编辑
以下是 AFAICT const
不是 "useful" 的一些情况:
- 任意 return 值(右值不能改变)。例如。
const int foo() { return 2; }
- 任意类型转换(仍然是右值...)。例如。
(int const) bar()
sizeof
(qualified/unqualified 类型的对齐方式和大小相同)。例如。sizeof(const int)
根据语言语法,type-qualifier 可以作为 type-name 的一部分出现。如果您查看 type-name 的语言语法,您会发现可以使用它的所有上下文。那将是:声明、转换、复合文字、泛型、sizeof
、_Atomic
、_Alignas
、_Alignof
.
可以肯定地说,在最后四个的上下文中 -
sizeof
、_Atomic
、_Alignas
、_Alignof
-const
在任何间接级别上都没有区别。_Generic
似乎仍未指定,但可以安全地假设顶级const
在那里没有区别。在更深层次的间接性中,const
在_Generic
. 中很重要
至于其他,管理规则是:顶级
const
仅对 lvalues 有意义。应用于 rvalues 时没有区别。这意味着将顶级 const 限定应用于函数 return 类型或强制转换中的目标类型是没有意义的。在更深层次的间接寻址中使用的限定词,显然很重要。
请注意,复合文字是左值,这意味着复合文字中的顶级
const
很重要int *p = (const struct { int a[10]; }) { 0 }.a; // Error: discards `const`
一些奇怪的例子仍然存在,例如
const struct S { int a[10]; } foo(void) { return (struct S) { 0 }; } int main() { int *p = foo().a; }
它在 GCC 中编译,但是,如果我没记错的话,行为无论如何都是未定义的。