为什么 printf 将 8 位字符填充到 32 位
Why does printf pad an 8-bit char to 32-bits?
char byte = 0xff;
printf("%lun", sizeof(byte)) // Output is '1'
printf("%xn", byte); // Output is 'ffffffff'
如果byte
的大小只有一个字节,那么为什么printf()
表现得好像是四个字节?
从形式上讲,你的程序表现出未定义的行为:%x
格式规范需要一个 unsigned int
类型的参数,但你传递的是一个int
,如下所述(帽子提示@R(。这在现代二进制补码机器上实际上是无害的,因为 int 和无符号具有兼容的位布局。但同样,从技术上讲,这是未定义的行为,修复它是一个好主意,就像在 printf("%xn", (unsigned)byte);
.
将参数传递给可变参数函数的规则规定,所有小于 int 的整型都会提升为 int。 否则,printf
怎么知道,在看到%x
时,是从堆栈中抓取一个字节还是四个字节?从标准:
5.2.2p7 :
当给定参数没有参数时,参数以接收函数可以通过调用va_arg(18.10)...
获取参数值的方式传递 如果参数具有受整型提升(4.5),
约束的整型或枚举类型,或者受浮点提升(4.6),
的浮点型,则参数的值将转换为呼叫前的升级类型。
这就是您的char
变成int
的方式.char
是有符号还是未签名是未签名的,但显然,在您使用的平台上,它是有符号的类型。因此,当提升为int
时,它会得到符号扩展。 0xff
是(char)-1
,0xffffffff
是(int)-1
。
我认为这是由于integer promotion
关于这个概念的一篇很好的博客文章:http://www.idryman.org/blog/2012/11/21/integer-promotion/
通过将错误的参数类型传递给printf
来调用未定义的行为。%x
说明符需要类型为 unsigned int
的参数,但您(由于默认升级(传递了已签名的int
。如果有符号int
参数的值为非负数,这可以说是有效的,但是在您的系统上,纯char
恰好是有符号类型,因此byte
包含将实现定义的转换应用于0xff
的结果;此转换的通常结果为 -1。
char
是 8 位有符号的。"%xn"
格式表示打印一个整数。因此,byte
的值是符号扩展为整数。由于0xff
的char
在这种情况下是 8 位值 -1
,printf
只是打印-1
的十六进制整数值,即ffffffff
。
- 流填充字符的默认定位
- 将十六进制值设置为用于填充的字符变量时出现问题
- 将空填充但不以空结尾的固定长度字符数组转换为 std::string 的最佳方法
- 填充字符数组的最佳方法(获取与cin.getline)
- 给定一个填充无符号字符**的 C 函数,如何在没有中间副本的情况下用数据填充 std::vector
- 如何填充项目为 8 个字符的集合?(std::set<char [8]>)
- 用字符串填充字符数组?C++
- 如何填充二维字符数组?C++
- 在计算使用了多少个数组索引的同时,如何填充一个来自用户输入的字符的数组?(使用cin.get)
- 我如何用单词填充二维字符阵列
- C/C++ 从字符缓冲区读取以填充结构
- 从 std::vector<无符号字符中的数据填充结构>
- 数组的第一个字符填充了不正确的数据C++
- 用字符填充二维数组
- 是否可以在C++中动态填充字符*数组
- ifstream get() 不填充字符数组
- 提升精神继承的字符串属性填充<int> ASCII 字符中的向量
- 使用 ifstream 剂量读取大型二进制文件不会填充字符缓冲区C++
- 分配后如何用字符串填充字符
- C++用多个字符串和浮点填充字符数组