我的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仍被转换为无符号整数。

10-04 12:31
查看更多