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