带有 const int* const 的 scanf 可以工作,但不应该
scanf with const int* const works, but shouldn't
我有如下代码:
const int* const n = new int;
printf("input: ");
scanf("%d", n);
delete n;
现在,因为n是一个指向常量整数的指针,这应该不起作用(我预计会出现编译错误)。然而,这似乎可以正常工作,甚至可以将输入的值存储到*n中。
我想知道,为什么这不会给我一个错误;为什么它会起作用?scanf不应该不能改变*n的值吗?
scanf的原型是:
int scanf ( const char * format, ... );
省略号表示它接受变量参数。C(和c++)没有办法检查这些参数的有效性。这就是为什么如果你在这里传递双精度变量的地址,甚至是双精度变量本身,你都不会得到错误。由程序员来验证传递的参数是否正确。
scanf
几乎没有类型安全,它很高兴地做你告诉它的事情。这是因为变量参数列表在c中实现的方式,它们期望类型是你告诉它的类型。
因此,如果您给scanf
一个不匹配的转换说明符,您将调用在运行时发生的未定义行为。类似地,编译器可能无法判断传递的指针是const type* const
类型。如果一个好的编译器发现了一些可疑的东西,它可能会给出一个诊断,但这绝不是必须的。
由于大多数未定义行为发生在运行时,因此了解各种形式的未定义行为并避免它们通常是程序员的责任。
由于scanf
是可变的,它在语法上是合法的传入几乎任何东西,因此它也应该编译。
虽然 最后, 将转换结果放置在format实参后面的第一个实参所指向的对象中,该对象尚未接收到转换结果。如果该对象没有适当的类型,或者转换的结果不能在该对象中表示,则该行为为未定义。 指针实际上是指向一个适当类型的对象;总之,我认为这是定义良好的(但令人困惑)行为。n
是指向const int
的指针,但它指向的对象实际上不是const对象。因此,修改int
对象(例如,通过使用const_cast
将指针转换为int*
) 是定义良好的行为。fscanf
的标准文档说
编译器可以发出警告,但它不会阻止你犯这样的错误,这是未定义的行为,const
只是用作指示符,它不会阻止编译。它工作正常,因为指针不是真正的const
,虽然它是UNDEFINED BEHAVIOR传递一个const
指针,但这不是真正的一个。
好吧,scanf
不会区分传递的参数,但如果你编译时启用了警告,编译器会警告你-
warning: writing into constant object (argument 2) [-Wformat]
- 为什么我不能声明一个 constexpr 本地,而一个 const 一个工作?
- 为什么带有 const 关键字的构造函数可以工作,而没有它就不能工作?
- 为什么在CTOR工作中将温度变量传递到const Ref中
- 为什么 vector::erase 不能在带有 const 的类元素上工作
- 'const std::string&s = nullptr' 如何作为可选参数工作
- OpenCV的"calcCovarMatrix"函数中"const Mat*样本"参数的工作原理?
- C++ extern const char* 未按预期工作
- STD ::配对的const引用如何工作
- 围绕缺乏外部库的const-correct性工作
- C++ 为什么我的覆盖代码 const int x = *(&y);工作?
- 返回const lvalue引用rvalue临时?为什么这项工作
- 带有 Qt 的正则表达式 - indexIn(const QString &) 无法按预期工作
- const char*和字符串比较在C++中是如何工作的
- 在const 2D数组上支持my_2D_Array[x][y](双运算符[]);无法使事情正常工作
- std::map::erase(const key_type&) 比较自定义后停止工作
- 带有 const int* const 的 scanf 可以工作,但不应该
- const和volatile的重载——为什么它可以通过引用工作
- 为什么 'const int ci = 2;std::forward<int>(ci);' 工作以及如何修复/解决它?
- 错误的静态const初始化,编译和工作
- c++数据成员.目标:在构造函数中初始化,然后不管,将const工作在这里