C语言 Printf执行隐式强制转换

fd3cxomn  于 2023-04-19  发布在  其他
关注(0)|答案(3)|浏览(133)

在下面的代码片段中,为什么我们会得到600的输出?两个问题将帮助我理解这种行为。
1.我将变量 b 的类型指定为 uint8_t,为什么数学运算不限制为相同的类型?
1.我认为 * PRIu 8 * 是打印uint8_t的正确类型,为什么不工作?
我希望得到的答案是88,这是由于循环超出了uint8_t的范围。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

void main()
{

    uint8_t b = 200;
    printf("%" PRIu8 "\n",b+b+b);
    printf("%" PRIu8 "\n",3*b);

}

gcc版本9.4.0(Ubuntu 9.4.0- 1ubuntu 1 ~20.04.1)

2j4z5cfb

2j4z5cfb1#

我认为这是一个图书馆的bug。
在MS Visual Studio中,宏PRIu8被扩展为hhu,您将获得预期的结果。
值得注意的是,如果要使用clang,那么如果您将编写例如

printf("%" PRIu8 "\n",( uint8_t)(b+b+b));

你会再次得到预期的结果。

disbfnqx

disbfnqx2#

在C语言中,无论何时用elipsis调用函数(...)参数,例如printf,所有这些参数都将经历 * 默认参数提升 *。这意味着任何较小的整数类型都将被转换为int并以这种方式传递。因此在printf中,h类型前缀是不相关的--它们将被printf忽略,并且没有任何效果(因为参数必须是int)。
此外,对于任何算术运算符(如+*),都将发生较小整数类型的相同转换,结果运算将以int精度执行,得到int结果。
要获得预期的结果,请将其显式掩码为适当的大小:

printf("%u\n", (b+b+b) & 0xff);
f4t66c6m

f4t66c6m3#

如果我们看一下inttypes.h,我们会发现以下内容:

# define PRIu8      "u"

因此,这个格式说明符不包含任何长度修饰符。这在其对应参数的上下文中是有意义的,因为不可能将uint8_t传递给可变参数函数。由于此类型的秩小于int,因此此类型的值将被提升为int。这种提升也发生在表达式b+b+b3*b中。
如果对char显式地使用长度修饰符,将得到预期的结果。

printf("%hhd\n",b+b+b);
printf("%hhd\n",3*b);

相关问题