c - printf char type in base16 出现混淆现象

标签 c printf

代码如下:

#include<stdio.h>
void f(unsigned char v)
{
    char c = v;
    unsigned char uc = v;
    printf("%%X: %X, %X\n", c, uc);
}

int main(int argc, char *argv[])
{
    f(0x80);   
    return 0;
}

结果:

%X: FFFFFF80, 80

我很困惑。 FFFFFF80怎么来的。我们知道 char 类型包含 1 个字节。我知道 charunsigned char 之间的区别在于它们处理最高位的方式,但两者都保存一个字节。 而且我认为该程序不涉及任何转换过程。 如果 c 的类型是 int(将 unsigned char 转换为 int),符号位将扩展。但在这种情况下,它是 unsigned char 转换为char但都保存一个字节

那么为什么 printf("%X",c) 的结果包含 4 个字节?

最佳答案

printf 是一个可变参数函数,它被定义为:

int printf(const char * fmt, ...);

也就是说,printf 不知道您传递给它的参数类型,它依赖于格式字符串来推断参数类型。

格式字符串后的每个参数都受到整数提升(char 被提升为 int)。

所以 printf 在你的情况下接收到的是一个格式字符串 ("%%X: %X, %X\n"),一个 int 包含 -128(因为 0x80 在二进制补码架构上表示为 char-128)和一个包含 128int

引用资料:

ISO C § 6.3.1.1:

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.

ISO C § 6.5.2.2:

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions.

The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.


附言 值得注意的是,您遇到的二进制补码行为是实现定义的,即 (char)0x80 不能保证等于 -128 在所有平台上。

关于c - printf char type in base16 出现混淆现象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44194546/

相关文章:

c - 为什么我的两个计算函数都会出现 Unresolved external 系统错误(错误 LNK2019)?

Ruby sprintf 在 1.9 中发挥作用

Perl 输出覆盖自身

java - System.out.printf( "%-15s%03d\n", s1, x) 做什么?

c - 作为进程子进程,如何知道哪个文件描述符是父进程

枚举可以容纳大于 INT_MAX 的无符号整数吗?

c - 从 PKCS11 token 读取对象

python - python和c中的内存分配

c - 来自十六进制整数的 printf UTF8 字符

c - printf() 在没有双引号的情况下工作,打印随机字符