scanf with const int * const可以工作,但不应该

时间:2015-10-27 13:37:54

标签: c++ const constants scanf

我的代码相当于以下内容:

const int* const n = new int;
printf("input: ");
scanf("%d", n);
delete n;

现在,因为n是指向CONSTANT整数的指针,所以这不应该工作(我期待编译器错误)。但是,这似乎可以正常工作,甚至可以将输入值存储到* n。

我想知道,为什么这不会给我一个错误;它为什么有效?扫描不应该无法改变* n?

的值

5 个答案:

答案 0 :(得分:23)

scanf的原型是:

int scanf ( const char * format, ... );

省略号表示它需要变量参数。 C(和C ++)无法检查这些参数的有效性。这就是为什么如果你传递double的地址或者甚至是double变量本身你都不会得到错误的原因。由程序员来验证是否传递了正确的参数。

答案 1 :(得分:5)

scanf旁边没有任何类型安全,它很乐意按照你的说法去做。这是因为变量参数列表在C中实现的方式。他们希望类型是你告诉它的类型。

因此,如果您为scanf提供一个不匹配的转换说明符,您将调用在运行时发生的未定义行为。类似地,编译器可能无法判断传递的指针是否为const type* const类型。一个好的编译器可以提供诊断,如果它发现了一些可疑的东西,但绝不需要这样做。

由于大多数未定义行为的情况都发生在运行时,因此程序员通常有责任了解各种形式的未定义行为并避免它们。

答案 2 :(得分:3)

由于scanf是可变参数,因此在语法上合法传递任何内容,因此它也应该编译。

虽然n是指向const int的指针,但它指向的对象实际上是而不是一个const对象。因此,修改int对象(例如,使用const_cast将指针转换为int*明确定义的行为。

最后,fscanf的标准文档说

  

转换的结果放在第一个参数指向的对象之后,该参数位于尚未收到转换结果的format参数之后。如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义。

实际上,指针指向适当类型的对象;总之,我认为这是明确定义(但令人困惑)的行为。

答案 3 :(得分:2)

编译器可以发出警告,但它不会阻止你犯这样的错误,它的未定义行为,const仅用作指示符,它不会阻止编译。并且它正常工作,因为指针实际上不是const,虽然它的 UNDEFINED BEHAVIOR 传递const指针,但这不是真的。

答案 4 :(得分:1)

好吧,scanf不会区分传递的参数,但如果你在启用警告的情况下编译,编译器会警告你 -

 warning: writing into constant object (argument 2) [-Wformat]