任何人都可以向相对新手解释以下行为......
const char cInputFilenameAndPath[] = "W:\\testerfile.bin";
int filesize = 4584;
char * fileinrampointer;
fileinrampointer = (char*) malloc(filesize);
ifstream fsInputFileStream;
fsInputFileStream.open(cInputFilenameAndPath, fstream::in | fstream::binary);
fsInputFileStream.read((char *)(fileinrampointer), filesize);
for(int f=0; f<4; f++)
{
printf("%x\n", *fileinrampointer);
fileinrampointer++;
}
我期待上面的代码将我刚读入的文件的前4个字节读入内存。在循环中,我只是显示指针指向的当前字节,然后递增指针准备好显示下一个字节。 当我运行代码时,我得到了:
37
ffffff94
42
ffffffd2
值正确但其他每个值似乎都填充到64位数。 因为我要求它显示由'char size'指针指示的值,所以我期待char大小的结果,但是其他所有结果都是长的。 如果我asign * fileinrampointer到一个无符号的__int8它给我留下了我想要的值(没有前导1)解决问题,但我只是想知道是否有人能解释上面发生了什么?
答案 0 :(得分:8)
表达式*fileinrampointer
的类型为signed char
,并且在传递给printf时会被提升为signed int
。因此,符号位传播。稍后,您使用%x
打印出来,这意味着unsigned int in hex
,这会导致您打印所有1(而不是正确地将它们解释为2的补码有符号整数的一部分)。此外,ffffffd2是8个十六进制数字,这意味着它是一个32位有符号整数。
如果您将fileinrampointer
声明为unsigned char
或unsigned __int8
,则促销期间符号位不会传播。您也可以将其签名并投下
printf("%x\n", static_cast<unsigned char>(*fileinrampointer) );
6。如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将具有float类型的参数提升为double。这些被称为默认参数促销。 [...]
[...]
7.如果表示被调用函数的表达式具有包含原型的类型,则将参数隐式转换为相应参数的类型,就像通过赋值一样,将每个参数的类型设置为不合格的版本它的声明类型。 函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数后停止。默认参数提升是在尾随参数上执行的。
这清楚地支持了我的声明,即这是整数提升,而不是printf解释。
另见
ISO/IEC 9899:1999 7.15.1.1
glibc manual A.2.2.4
glibc manual 12.12.4
securecoding.cert.org
答案 1 :(得分:1)
您不是要求它显示由字符大小指针指示的值,而是要求它使用char指针的内容显示十六进制整数(%x)。没试过,但你可以尝试施放它:
printf("%x\n", (unsigned int)(*fileinrampointer));