【问题标题】:Why doesn't gcc emit a format warning?为什么 gcc 不发出格式警告?
【发布时间】:2021-12-27 19:07:39
【问题描述】:
#include <stdio.h>

void a(signed char a) {
    printf("%u\n", a);
}

void b(short b) {
    printf("%u\n", b);
}

void c(int c) {
    printf("%u\n", c);
}

void d(long d) {
    printf("%u\n", d);
}

void e(long long e) {
    printf("%u\n", e);
}

int main() {
    a(-1); //no warning
    b(-1); //no warning
    c(-1); //no warning
    d(-1); //warning
    e(-1); //warning
    return 0;
}

使用gcc -std=c17 -pedantic -Wall -Wextra test.cg++ -std=c++17 -pedantic -Wall -Wextra test.cpp 使用gcc 11.2.0 编译和测试。两者都不会对a()b()c() 发出任何警告。这是故意的,还是一个错误?

【问题讨论】:

  • 您希望得到什么样的警告?您的问题中缺少该部分...
  • 您期待什么警告?您实际上收到了哪些警告?不要假设每个人都在使用 gcc。
  • 他们为什么要这样做? -1 是显示的每个函数的可接受参数值。
  • 是的,但 %u 仍然会与 int 值不匹配,无论是否提升。 gcc 对printf 参数进行编译时验证。
  • @Remy Lebeau Re "%u 仍然会与 int 值不匹配",-Wformat-signedness 会发现这一点。

标签: c++ c gcc


【解决方案1】:

简短回答:C 警告是一个谜。如果您想在此处收到警告,请使用 -Wformat-signedness

注意-Wformat-signedness 需要-Wformat-Wall 已经启用。


显然,编译器仅在使用-Wformat-signedness 时检查符号不匹配。 -Wall-Wextra 不包括 -Wformat-signedness。我不知道这是为什么。有人说这是因为它会导致太多警告,但这告诉我,如果它是一个常见的错误,它真的需要使用!

所以,所有被检查的是尺寸不匹配。发出警告的两个(de)发出警告,因为正在传递一个可能大于 int 的类型的值。至于另外两个,signed charshort int 值在传递给像 printf 这样的可变参数 (...) 函数时被提升为 int 值,所以 ab 等价于 c .

【讨论】:

  • 不,所有被检查的是正确性。 floatint 通常具有相同的大小,但编译器会警告您,因为将 float 重新解释为 int 是无效的。 (IIRC 也不允许将 long 解释为 int即使它们具有相同的大小)。 但始终允许将 int 重新解释为 unsigned int(反之亦然)。
  • @numzero 问题不在于整数类型与非整数类型的兼容性,也不是这个答案。不,“不正确”是一个错误的词。这将包括符号不匹配。
  • s/正确性/明确定义/。通过unsigned* 读取int 是明确定义的,而通过float*(甚至long* IIRC)读取则不是,即使所有这些类型具有相同的大小。
  • @numzero 同样,浮动是题外话。指针也是如此。我们正在讨论整数。为什么我认为我关心它们的非整数大小。
  • 您是否不同意printf("%d", 0L) 是UB 而printf("%d", 0u)sizeof(int) == sizeof(long) 无关?
猜你喜欢
  • 2018-07-18
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多