分配结构值时 const 关键字的用途是什么?
What is the use of the const keyword when assigning structure values?
const
关键字在这个程序中有什么用?
#include <stdio.h>
struct x{
int a;
int b;
};
int main()
{
struct x xx;
xx = (const struct x) {0};
xx.a = 10;
printf("%d, %d", xx.a, xx.b);
}
当我 运行 没有 const
关键字时,输出没有区别。它在这里有什么意义?
But what is it's significance here?
None.
当您像 xx = something;
一样分配给 xx
时,您需要 something
具有基本类型 struct x
。发生这种情况是由于演员阵容。所以如果你这样做
(struct x) {0};
将创建一个类型为 struct x
的匿名对象,并且可以将其分配给 xx
,例如:
xx = (struct x) {0};
现在在强制转换中添加 const 限定符意味着匿名对象是常量。但是,它保持不变并不重要,因为无论如何您都不会写入它。对匿名对象执行的唯一操作是在对 xx
赋值期间执行的读取操作。对于赋值,源对象(RHS 对象)是否为常量没有区别。
所以:不,对于您的代码 const
没有任何意义。
我们可以在重要的地方构建代码吗?
是的,考虑这个(混淆无用的)代码:
int y;
y = ++(struct x) {0, 42}.b;
printf("%d\n", y);
它将创建一个匿名对象,其值为 .a=0
和 .b=42
,然后递增 return .b
。换句话说,它将打印 43.
如果您将 const
添加到转换中,您将得到一个编译器错误,例如:
main.cpp:26:9: error: increment of member 'b' in read-only object
26 | y = ++(const struct x) {0, 42}.b;
| ^~
所以这里 const
关键字很重要。
这将零初始化一个临时 struct x
:
xx = (const struct x) {0};
然后该临时文件将用于复制分配 xx
。无论临时对象是否为 const
,它都会执行此操作。
一个流行的编译器 (gcc) 的示例表明,在 const
和非 const
的情况下,它将简单地将 xx
中的两个成员清零,而不实际上创建一个临时对象。编译后的程序表现得 就好像 一样:
xor edx, edx
xor esi, esi
C 2018 6.3.2.1 2 表示当任何对象在表达式中用作其值时,诸如 const
的限定符将被删除:
Except when it is the operand of the sizeof
operator, the unary &
operator, the ++
operator, the --
operator, or the left operand of the .
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue.
因此,在xx = (const struct x) {0};
中,(const struct x) {0};
是一个创建const struct x
对象的复合文字。但是,在获取此对象的值时,const
被删除,结果是 struct x
值。 (结构的“值”是其所有成员值的总和。)
因此,在这种使用中,const
最终没有作用。但是,复合文字确实创建了一个 const
对象。这种效果可以在其他用途中看到。例如,使用 const struct x *p = & (const struct x) {0};
,我们获取复合结构的地址。然后,如果我们尝试删除 const
并修改结构,如 ((struct x *) p)->a = 3;
,C 标准未定义该行为。编译器可能已将该结构置于只读存储器中,并试图修改它可能会产生一个陷阱。或者,在优化期间,编译器可以使用结构是 const
的事实来忽略它可能更改的任何可能性。例如,在:
const struct *p = & (const struct x) {0};
((struct x *) p)->a = 3;
printf("%d\n", p->a);
程序可能会打印“0”,因为在 printf
中的 p->a
中,编译器使用 p->a
被定义为 const
零这一事实.
const
关键字在这个程序中有什么用?
#include <stdio.h>
struct x{
int a;
int b;
};
int main()
{
struct x xx;
xx = (const struct x) {0};
xx.a = 10;
printf("%d, %d", xx.a, xx.b);
}
当我 运行 没有 const
关键字时,输出没有区别。它在这里有什么意义?
But what is it's significance here?
None.
当您像 xx = something;
一样分配给 xx
时,您需要 something
具有基本类型 struct x
。发生这种情况是由于演员阵容。所以如果你这样做
(struct x) {0};
将创建一个类型为 struct x
的匿名对象,并且可以将其分配给 xx
,例如:
xx = (struct x) {0};
现在在强制转换中添加 const 限定符意味着匿名对象是常量。但是,它保持不变并不重要,因为无论如何您都不会写入它。对匿名对象执行的唯一操作是在对 xx
赋值期间执行的读取操作。对于赋值,源对象(RHS 对象)是否为常量没有区别。
所以:不,对于您的代码 const
没有任何意义。
我们可以在重要的地方构建代码吗?
是的,考虑这个(混淆无用的)代码:
int y;
y = ++(struct x) {0, 42}.b;
printf("%d\n", y);
它将创建一个匿名对象,其值为 .a=0
和 .b=42
,然后递增 return .b
。换句话说,它将打印 43.
如果您将 const
添加到转换中,您将得到一个编译器错误,例如:
main.cpp:26:9: error: increment of member 'b' in read-only object
26 | y = ++(const struct x) {0, 42}.b;
| ^~
所以这里 const
关键字很重要。
这将零初始化一个临时 struct x
:
xx = (const struct x) {0};
然后该临时文件将用于复制分配 xx
。无论临时对象是否为 const
,它都会执行此操作。
一个流行的编译器 (gcc) 的示例表明,在 const
和非 const
的情况下,它将简单地将 xx
中的两个成员清零,而不实际上创建一个临时对象。编译后的程序表现得 就好像 一样:
xor edx, edx
xor esi, esi
C 2018 6.3.2.1 2 表示当任何对象在表达式中用作其值时,诸如 const
的限定符将被删除:
Except when it is the operand of the
sizeof
operator, the unary&
operator, the++
operator, the--
operator, or the left operand of the.
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue.
因此,在xx = (const struct x) {0};
中,(const struct x) {0};
是一个创建const struct x
对象的复合文字。但是,在获取此对象的值时,const
被删除,结果是 struct x
值。 (结构的“值”是其所有成员值的总和。)
因此,在这种使用中,const
最终没有作用。但是,复合文字确实创建了一个 const
对象。这种效果可以在其他用途中看到。例如,使用 const struct x *p = & (const struct x) {0};
,我们获取复合结构的地址。然后,如果我们尝试删除 const
并修改结构,如 ((struct x *) p)->a = 3;
,C 标准未定义该行为。编译器可能已将该结构置于只读存储器中,并试图修改它可能会产生一个陷阱。或者,在优化期间,编译器可以使用结构是 const
的事实来忽略它可能更改的任何可能性。例如,在:
const struct *p = & (const struct x) {0};
((struct x *) p)->a = 3;
printf("%d\n", p->a);
程序可能会打印“0”,因为在 printf
中的 p->a
中,编译器使用 p->a
被定义为 const
零这一事实.