函数正在转换 uint8 <-->uint16?

Function is casting uint8 <-->uint16?

我正在对我的代码进行单元测试 (UT),我发现了一些奇怪的地方,也许有人可以向我解释一下。 我有两个类似于这条线下面的功能。当我从测试中调用“fun_16bit”时,我传递了一个高于 255 的值以查看“fun_8bit”的作用。如果我写 value=256 -->fun_8bit 将打印 0。如果我从 UT fun_8bit 调用 value=-1--> 它打印 255.

这是怎么回事????? 为什么 func8bit 只取前 8 位而编译器不说明什么?

顺便说一句,我正在用 gcc 编译 C。

void fun_16bit(uint16_t value)
{
    printf("value: %d", value);
    fun_8bit(value);
}

void fun_8bit(uint8_t value)
{
    printf("value: %d", value);
}



int main() {
  fun_16bit(0x1234);
}

预期输出:来自编译器的一些错误或警告 实际输出: 值:1234 值:34

谢谢大家。

256 表示您的数字的前 8 位为 0,第 9 位为 1。当您将其转换为 uint8_t for fun_8bit 时,您的函数只会看到 8 位为 0 . 至于第二种情况,uint 的 -1 表示所有位为 1。在 fun_16bit 中表示 16 位的 1。当您将其转换为 uint8_t 时,您会得到 8 位的 1(意思是255)

我不明白这里的问题:

让我们来看看这里的一些数字:

  • uint8_t只取二进制格式的最后八位,而uint16_t取最后十六位。
  • -1 定义为需要加 1 才能得到 0 的值,二进制格式没有标准的写法。

这是结果:

Decimal value    Binary value     uint8_t value    uint16_t value
          256       100000000          00000000  0000000100000000
          255        11111111          11111111  0000000011111111
           -1          11...1          11111111  1111111111111111

因此,如您所见:
二进制格式的 256 是一个 1,后跟八个 0 数字。当您取最后八位数字(转换为 uint8_t)时,您只会得到零。
255 只是一堆 1 数字,与 uint8_t 格式中的 -1 相同。
如果你想要 uint16_t 中的 -1,65535 就是你需要的数字。

您询问的是以下转换。

  • (uint16_t)-1 导致 65535
  • (uint8_t)-1 导致 255
  • (uint8_t)65535 导致 255

C 规范要求这些结果。

6.3.1.3 Signed and unsigned integers

  1. When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.

  2. Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value can be represented in the new type until the value is in the range of the new type.[60]

  3. Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

(强调我的)

  • (uint16_t)-1 等价于 (uint16_t)65535 因为 -1 + 65536*1 = 65535.
  • (uint8_t)-1 等价于 (uint8_t)255 因为 -1 + 256*1 = 255.
  • (uint8_t)65535 等同于 (uint8_t)255 因为 65535 - 256*255 = 255.

实际上,在二进制补码机上,

  • 转换为 uint16_t 需要最后 16 位。
  • 转换为 uint8_t 需要最后 8 位。

gcc 通常不会警告缩小类型转换和有符号到无符号类型转换,但 -Wconversion 会启用此类警告。