我的C++程序在dev c++编译器上运行良好。但现在我想在Visual Studio 2013上运行它的win32控制台,但出现错误:负常量转换为无符号类型
你能告诉我如何解决吗?
void modifystudent(int id)
{
fstream file;
file.open("users11.txt",ios::in | ios::out);
student obj;
system("cls");
while (file.read((char*)&obj, sizeof(obj)))
{
if (obj.givid() ==id)
{
cout << "\nPlease enter new details of student";
obj.getrecord(); //// error is here negative constant converted to unsigned type
int pos = -1 * sizeof(obj);
file.seekp(pos, ios::cur);
file.write((char*)&obj, sizeof(obj));
cout << endl << " Record is Modified.." << endl;
}
}
file.close();
// free(obj);
}
最佳答案
gcc和VS都会在此处发出警告。在VS下出现错误的原因是因为您可能已启用/WX
选项,该选项将警告视为错误。一个简单的解决方案是在乘法之前将sizeof(obj)
转换为int:
int pos = -1 * static_cast<int>(sizeof(obj));
更长的解释:
在此表达式中:
int pos = -1 * sizeof(obj);
-1
的类型为int
,而sizeof(obj)
的类型为size_t
,而我们对size_t
所了解的只是它是无符号整数-我想它的宽度通常为4或8个字节。进行乘法运算之前,编译器将尝试将两个操作数转换为通用类型,这些转换是隐式的。现在适用于此处的转换规则:当有符号整数乘以无符号,并且无符号操作数等于或大于有符号操作数时,有符号操作数将转换为无符号。
因此,如果
sizeof(int)
是4个字节,而sizeof(size_t)
是8个字节,则首先将-1
转换为等于static_cast<size_t>(-1)
的0xffffffffffffffff
。然后完成乘法,然后再应用另一次转换-乘法结果转换为int。因为sizeof(obj)
在编译时是已知的,所以编译器将知道确切的值,如果sizeof(obj)
为1,则乘法结果为0xffffffffffffffff
,并且其结果太大而无法分配给int
变量而不会被截断,因此编译器会警告您有关所需的隐式转换。根据
size_t
的大小,编译器在此处给出不同的警告:当乘法结果转换为int(x64编译,sizeof(size_t)== 8)时,clang通知最后一个阶段:
main.cpp:15:17: warning: implicit conversion from 'unsigned long' to 'int' changes value from 18446744073709551615 to -1 [-Wconstant-conversion]
int pos = -1 * sizeof(obj);
~~~ ~~~^~~~~~~~~~~~~
(18446744073709551615是0xffffffffffffffffff)
gcc看起来很相似,但信息量较少(x64编译,sizeof(size_t)== 8):
main.cpp:16:29: warning: overflow in implicit constant conversion [-Woverflow]
int pos = -1 * sizeof(obj);
另一方面,Visual Studio 2015警告将-1转换为无符号类型(在x86版本中,sizeof(size_t)== 4):
warning C4308: negative integral constant converted to unsigned type
我想它会通知此转换
static_cast<size_t>(-1)
。并在x64(sizeof(size_t)== 8)中关于常量值的截断(与上述gcc和clang相同的警告)
warning C4309: 'initializing': truncation of constant value
但由于某些原因,不再显示C4308,即使-1仍被转换为无符号整数。