假设我有一个局部变量int var;
,我用它来调用另一个函数来检索一些值,如下所示:func(..., &var);
。
然后我检查某些事物的检索值并采取相应的行动。变量var
收到其值后,var
将永远不会再从该点开始更改。
那么将var
定义为 const 是否有意义? (int const var;
)。
我不确定这是否是使用 const 关键字的正确方法,因为var
的初始值是堆栈遗留的内容并且更改调用func
时:func(..., &var);
。因此,在某种程度上与 const 类型限定符相矛盾。
我之所以不确定这是因为将变量var
定义为 const (int const var;
)的效果(或结果)是理想的var
范围内的代码行为。
也就是说,不应该允许使用赋值运算符直接更改var
的值,即使var
函数中的某个指针刚刚更改了func
的值。
示例
int foo(void)
{
int const var;
if (!func(..., &var))
return 0;
if (var == x)
// do some stuff
else if (var == y)
// do some other stuff
else
// nope
return var * x + y;
}
我想知道在正确性方面,用于定义var
的 const 类型限定符是否仍适用于该情况。
关于正确性,至少用gcc你可以传递你的const var 修改功能,但它会生成警告。我不会 建议也不要这样做。它并没有帮助而不是混淆读者。
似乎我错误地解释了MSVC的最终行为,从而错失了错误的道路。在启用/Wall
的同时,MSVC产生的唯一警告是const object should be initialized
。我没有多想,因为只是初始化var
,看看会发生什么,结果是一个干净的编译。
但我认为我至少知道发生了什么。如果您有 const 数据类型,编译器会认为您不应该写入只读的内容,即使使用指针也是如此。因此,唯一一次让编译器看到传递给函数的 const 变量的地址是有意义的,当该变量包含除垃圾值之外的任何内容时。因此初始化警告。
如果在你的例子中使用var进行相等比较,那么就可以使用var const可以避免if(var = ...)与if(var == ...)拼写错误,因为 编译器会抓住它。
关于在尝试捕获此错误时是否使用 const ;我认为它更多地与确保编译器根据标准中定义的规则吐出一些东西有关,而不是编译器产生或不产生警告,如果 const 被省略var
的定义。
答案 0 :(得分:1)
你可以用另一个函数来包装它。
int wrapfun() {
int var;
func(..., &var);
return var;
}
int main()
{
const int var = wrapfun();
}
答案 1 :(得分:1)
扩展Eric Postpischil的答案,你也可以将var应该是const的块提取到一个新函数中,var作为const参数。这是否有意义取决于该块中实际发生的事情以及需要处理的其他动态状态。我会选择更易读的解决方案。
如果在代码的某些部分将var声明为const,则确保之后无人无意中对更改var值的代码进行了更改。您可以明确表达对该变量的意图,这可能有助于读者理解代码。如果在例子中使用var进行相等比较,那么使它成为const就可以避免if (var = ...)
与if (var == ...)
错误,因为编译器会捕获它。
关于正确性,至少使用gcc,可以将const var传递给修改函数,但它会生成警告。我既不会推荐,也不会这样做。它并没有帮助而不是混淆读者。
// const.c
#include <stdio.h>
void func(int *var)
{
*var = 5;
}
void post(const int var)
{
printf("%d\n", var);
}
int main(int argc, char *argv[])
{
const int var;
func(&var);
post(var);
return 0;
}
$ gcc const.c
const.c:在函数'main'中:
const.c:16:10:警告:传递'func'的参数1从指针目标类型中丢弃'const'限定符[-Wdiscarded-qualifiers]
func(&var);
^
const.c:3:6:注意:期望'int *'但参数类型为'const int *'
void func(int *var)
^~~~
所以在这种情况下,我会在main
中没有const,但你可以将它保存在post
中。
答案 2 :(得分:0)
你可以做到这一点,但它很难看:
int var;
func(..., &var);
{
const int sneaky = var, var = sneaky;
// var is const here.
...
}
这将打开一个新块,定义sneaky
以暂时保留var
的值,然后定义隐藏旧var
的新var
。由于隐藏了旧的var
,因此我们无法使用旧的var
初始化新的sneaky
,因此我们使用struct Point
{
int x;
void(*func)(struct Point*, int);
};
void addToX(struct Point* a, int b) {
a->x += b;
}
void main() {
struct Point p1;
p1.x = 3;
p1.func = &addToX;
printf("%d\n", p1.x);
p1.func(&p1, 2);
printf("%d\n", p1.x);
}
中隐藏的值初始化新Point
。