gpt4 book ai didi

c - 为什么 GCC 的 -Wconversion 对于 char 与 unsigned char 的行为不同?

转载 作者:太空狗 更新时间:2023-10-29 17:11:43 25 4
gpt4 key购买 nike

考虑

U8 foo(U8 x, U8 y) {
return x % y;
}

如果 U8(x 和 y 的类型)是 char 或 unsigned char,则 GCC 的 -Wconversion 行为不同:

gcc -Wconversion -c test.c -DU8='unsigned char'

(无警告)

gcc -Wconversion -c test.c -DU8=char
test.c: In function ‘foo’:
test.c:2:14: warning: conversion to ‘char’ from ‘int’ may alter its value [-Wconversion]
return x % y;
~~^~~

但是from what I understand在这两种情况下,x、y 都会进行整数提升(到 int 或 unsigned int),因此在这两种情况下,它将从 int 转换为任何返回类型(char 或 unsigned char)。

为什么会有差异?

奖励问题:如果您启用 ubsan (-fsanitize=undefined),那么 GCC 在这两种情况下都会发出 -Wconversion。

编辑:

x,y经过整型提升后需要转换为结果类型,没有说法,不用解释。

这里唯一的问题是为什么 GCC 对不同类型的行为不同。答案将涉及对 GCC 内部结构的一些了解。

最佳答案

长见识

仅使用有关类型的信息,gcc 应该对这两种情况发出警告,因为从 int(较大的类型)转换为 char/unsigned char(较小的类型)

还使用有关可能值的信息(范围分析)gcc 应该警告 none 因为 x % y 的结果,即使在提升为 int 之后,也总是适合回到与 xy 相同的类型。

因此,在第一种情况下,gcc 似乎可以断言操作永远不会导致值更改,但出于某种原因,在第二种情况下不能这样做。

作为旁注,clang 不会发出任何警告。


类型系统

  • 在测试系统 (x86-64) 上,char 类型已签名。请注意,它仍然是与 signed char 不同的类型。

  • x % y 由于整数提升规则,在这两种情况下,xy 都被提升为 int 。结果 x % y 的类型为 int

  • 如果我们将所有隐式转换显式化,那么我们会得到:

    unsigned char foo1(unsigned char x, unsigned char y)
    {
    return (unsigned char)((int) x % (int) y);
    }

    char foo2(char x, char y)
    {
    return (char)((int) x % (int) y);
    }
  • intcharunsigned charsigned char 的隐式转换会触发警告使用-Wconversion:

    -Wconversion

    Warn for implicit conversions that may alter a value. This includes [..] and conversions to smaller types

    事实上,这两个函数都会导致生成警告:

    char bar1(int a)
    {
    return a; // warning: conversion from 'int' to 'char' may change value [-Wconversion]
    }

    unsigned char bar2(int a)
    {
    return a; // warning: conversion from 'int' to 'unsigned char' may change value [-Wconversion]
    }

所以只使用类型信息我们应该得到警告,因为我们的 2 个函数有从 intchar/unsigned char 的隐式转换> 就像 bar1bar2 一样。

值(value)分析

如果我们使用符号 r = x % y 那么 rx|r| 具有相同的符号∈ [0, |y|).

  • 如果 xyunsigned char 类型,则 r ∈ [0, CHAR_MAX).

    r 适合 unsigned char。所以不需要警告。

  • 如果 xychar 类型:

    • CHAR_MIN = -CHAR_MAX - 1
    • max(|y|) = CHAR_MAX + 1
    • |r| ∈ [0, 最大值(|y|))
    • |r| ∈ [0, CHAR_MAX + 1)
    • r ∈ (-CHAR_MAX - 1, CHAR_MAX + 1)

    r 适合 char,因此不需要警告。

所以我要争论的是 x % y 的结果总是适合 U8 即使在所有整数提升和隐式之后也是如此转化。


你可以看看这个godbolt

关于c - 为什么 GCC 的 -Wconversion 对于 char 与 unsigned char 的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44795474/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com