如何解决scanf() 是否更新常量变量?
似乎 scanf()
更新了常量变量。
据我所知,常量变量应该有固定值。
在下面的代码中...
#include <stdio.h>
int main () {
const int testInteger = 0;
printf("Before 'scanf',the value of the variable 'testInteger' is %d.\n",testInteger);
// Does 'scanf' update constant variables?
printf("Enter an integer: ");
scanf("%d",&testInteger);
printf("After 'scanf',testInteger);
return 0;
}
...通过输入“50”的值,它给出以下输出:
Before 'scanf',the value of the variable 'testInteger' is 0.
Enter an integer: 50
After 'scanf',the value of the variable 'testInteger' is 50.
我想知道为什么 scanf()
会更新 'testInteger' 常量变量的值。
解决方法
是的,它应该具有恒定值,但它并不能神奇地保证它。
您获取了这个变量的地址(const int *
类型),它只不过是一个指向某个内存的数字。然后,通过将它传递给 scanf
,你违反了 const-ness 的契约(你没有收到任何警告吗?你用 -Wall
编译吗?):它被用作常规 {{1 }} 指针。
C 依赖硬件来强制 const
变量的只读性。大多数计算机硬件只能强制读取大内存块(称为“页面”),而不是单个 int
大小的变量。
您将 testInteger
声明为 const int
,但是因为它是一个普通的局部变量——它具有“自动存储持续时间”,在 C 标准的语言中——它的存储是分配在一个位置(称为“堆栈”)中,该位置的大块必须保持可写才能正常运行程序,因此硬件无法强制执行其const
性。
如果将 testInteger
的声明更改为 static const int testInteger
,或者将其声明为全局,那么它将被分配在为 const
变量保留的特殊内存区域中( “只读数据段”),其内存块是不可写的,当您的程序尝试写入 scanf
时,它会在 testInteger
的内部崩溃。
将 const
数据对象声明为全局对象/具有静态存储持续时间无论如何几乎总是正确的,因此这种硬件限制在实践中并不是什么大问题。 (嗯,实际上,这很重要,但原因完全不相关。)
这里有几个问题。
首先,const
only 的意思是“这个东西可能不是赋值运算符的目标”,不是“这个东西必须存储在 read-只有记忆。”如果 const
限定的变量是赋值运算符的目标,编译器只需要求发出诊断信息。
其次,%d
的 scanf
转换说明符需要 int *
类型的参数,但我们传递的是 const int *
类型的参数。然而,这并不像赋值那样约束违反,因此不需要诊断。由于我们将错误类型的参数传递给该转换说明符的 scanf
,因此行为未定义,这意味着编译器和运行时环境都不需要处理任何特定方式的情况。在这种情况下,您的实现更新了变量。在 testInteger
was 存储在只读内存中的实现中,您可能会遇到段错误或其他运行时错误,或者变量可能根本没有更新。
VC 不会警告您,您必须添加 -Wall,我使用的是 Dev C 或 Geany。不过,这不是编译器错误,只是一个不受欢迎的输出。
,我相信有些操作系统和编译器可以将常量变量存储到只读内存中,但我也相信大多数情况下都不会这样做。这更像是一种让编译器知道“如果我试图错误地更改此变量的方法,我希望您警告我”,但编译器不会检查指向它的指针,而只会检查直接引用。>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。