我试图在C中编写一个函数来打印出通用数据类型值的十六进制表示。我的第一次尝试失败了,第二次成功了,为什么?
首次尝试
#include <stdio.h>
/* prints out the hexadecimal representation of a generic value */
void show_hex(void*,size_t);
int main() {
int i = 12345;
short s = 32767; /* 2^15 - 1 */
show_hex(&i, sizeof(int));
show_hex(&s, sizeof(short));
return 0;
}
void show_hex(void *x, size_t sz){
char *cx = x;
int i;
printf("0x");
for (i = 0; i < sz; ++i)
printf("%.2x", cx[i]);
printf("\n");
}
在小端机器(Mac OSX)上按预期0x39300000
案例输出int
。对于short
案例,它会输出0xffffffff7f
而不是0xff7f
。
第二次尝试:
typedef unsigned char *byte_pointer;
int main() {
int i = 12345;
short s = 32767; /* 2^15 - 1 */
show_hex((byte_pointer)&i, sizeof(int));
show_hex((byte_pointer)&s, sizeof(short));
return 0;
}
void show_hex(byte_pointer x, size_t sz){
int i;
printf("0x");
for (i = 0; i < sz; ++i)
printf("%.2x", x[i]);
printf("\n");
}
此程序按预期输出int: 0x39300000
和short: 0xff7f
scrollable : {
direction : 'horizontal',
directionLock : true
},
答案 0 :(得分:4)
对于第一种情况,请更改:
printf("%.2x", cx[i]);
到
printf("%.2x", cx[i] & 0xFF);
普通char
类型已签名,因此0xFF符号扩展为所有F的8字节值,如打印输出中所示。
第一个数字工作正常,因为所有字节都在0x00..0x7F范围内,因此该值未转换为负整数 - 它保持正数。第二个数字无法解决,因为其中一个字节在0x80..0xFF范围内,因此被转换为负整数。并且%.2x
将始终打印所有数字,但如果只有一个,则在该数字之前将有0。 x
需要unsigned int
。
使用printf()
和其他可变参数函数,参数列表的...
部分中的参数是默认提升的,因此char
类型(所有变量)被提升为{{1} }(按int
),short
被提升为float
。
这在C标准(ISO / IEC 9899-2011)中有记载:
6.5.2.2函数调用
6如果表示被调用函数的表达式具有不包含a的类型 原型,对每个参数执行整数提升,并对其进行参数化 将类型
double
提升为float
。这些被称为默认参数 促销。 ......7如果表示被调用函数的表达式具有包含原型的类型, 参数被隐式转换,就像通过赋值一样,转换为类型 相应的参数,将每个参数的类型作为不合格的版本 其声明的类型。函数原型声明符中的省略号表示法导致 参数类型转换在最后声明的参数后停止。默认参数 促销是在尾随参数上进行的。
8不会隐式执行其他转换;特别是,数量和类型 参数不与函数定义中的参数进行比较 不包含函数原型声明符。
第6段的其余部分包括:
如果使用包含原型的类型定义函数,并且 原型以省略号(
double
)或......结尾,行为未定义。
必须在'如果表示被调用函数的表达式具有不包含a的类型的上下文中读取该句子
原型,...'在段落的开头。这意味着如果您调用使用省略号, ...
定义的函数,但在调用时范围内没有原型,则行为未定义。无论何时调用可变参数函数,都必须确保在范围内有原型。