【问题标题】:Inverted arguments in scanf()scanf() 中的倒置参数
【发布时间】:2012-10-15 15:19:25
【问题描述】:

我(很快)写了一些代码,不小心颠倒了scanf()中的参数:

char i[] = "ABC1\t";
scanf(i, "%s");

使用gcc -Werror -Wall -Wextra 编译不会抱怨这一点。显然,这段代码不起作用,但为什么 gcc 没有通知我我倒置了参数?它不能检测到i 不是格式字符串,或者第二个参数不是可存储类型吗?

编辑
感谢大家的洞察力,看起来我找到了答案,-Wformat 标志上有一个扭曲,使这个“可捕获”(发布在下面以供参考)

【问题讨论】:

    标签: c gcc compiler-errors


    【解决方案1】:

    哈!我找到了。用-Wformat=2 标志击中 gcc 捕获它。

    发布信息供他人参考:

    这是list of flags I found

    -Wformat Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified...

    我原以为-Wall 里面有-Wformat,它确实如此,但关于我刚刚发现的真正重要的部分:

    -Wformat is included in -Wall. For more control over some aspects of format checking, the options -Wformat-y2k, -Wno-format-extra-args, -Wno-format-zero-length, -Wformat-nonliteral, -Wformat-security, and -Wformat=2 are available, but are not included in -Wall.

    【讨论】:

    • 是的,+1 我也在找它。\
    【解决方案2】:

    我想不应该。

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

    i通常被转换为const char*,其余参数只是“省略号”,无法在编译时检查。

    【讨论】:

    • GCC 使用的 headers 通常将第一个参数标记为格式字符串,然后它可以确保将正确的类型传递给其余参数,前提是提供了-Wformat。我相信这是-Wall 的一部分。
    • @Will 但话又说回来 - 非 const char* 作为格式字符串(本身有效)传递,因此编译器没有强制进行参数检查。如果格式字符串是const char* 或文字,它可能已经这样做了。
    • 可能它不会在 'char* fmt' 和 'const char* fmt' 之间进行检查。谁能告诉,如果第二个参数(“ABC\t”)是 char* 还是 const char*?
    • 编辑:可能它不会在 'char* fmt' 和 'const char* fmt' 之间进行检查。谁能告诉,如果第二个参数(“ABC\t”)是 char* 还是 const char*?顺便说一句,第二个参数将被完全忽略,因为格式字符串不包含任何 % 格式字符。
    • 问题是 glibc 用 __attribute__((format(scanf, 1, 2))) 定义了 scanf,这是一个 gcc 选项,告诉它检查参数并发出警告。否则,很明显该问题没有类型不匹配错误。
    【解决方案3】:

    scanf (man scanf) 的手动输入给出了原型:

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

    char[] 只是 char * 的一种特殊类型,所以满足第一个参数。次要参数是在运行时评估的(如果我记得的话),所以这里的编译器甚至不考虑它们。从编译器的角度来看,这是对给定原型的函数的良好调用。

    此外,编译器从不检查您是否尝试写入无效位置。 C 语言的伟大(或可怕)之处在于,它可以让你或多或少地做你想做的事,即使你想做的是一个坏主意。

    【讨论】:

    • scanf 本身确实接受这些,但在 glibc 中,用 gcc 编译,scanf 有 __attribute__((format(scanf, 1, 2))) 告诉编译器确保参数正确,即使这不是由scanf 的声明强制执行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 2015-04-19
    • 1970-01-01
    相关资源
    最近更新 更多