C++ 为什么可能丢失数据的赋值不会产生编译器警告

C++ 为什么可能丢失数据的赋值不会产生编译器警告,c++,casting,warnings,stdint,C++,Casting,Warnings,Stdint,我正在使用MS Visual Studio 2017,并且(正如预期的那样)我收到了编译器警告: Warning C4244 '=': conversion from 'unsigned long' to 'unsigned short', possible loss of data 这个C++代码: unsigned long test32{70000}; unsigned short test16; test16 = test32; 但是,当我使用cstdint typedefs时:

我正在使用MS Visual Studio 2017,并且(正如预期的那样)我收到了编译器警告:

Warning C4244   '=': conversion from 'unsigned long' to 'unsigned short', possible loss of data
<>这个C++代码:

unsigned long test32{70000};
unsigned short test16;
test16 = test32;
但是,当我使用cstdint typedefs时:

uint32_t test32{70000};
uint16_t test16;
test16 = test32;
…我根本没有收到任何编译器警告。为什么?


此外,作为严格类型的语言,C++编译器不应该给我错误而不是对这些方法中的任何一个警告(并且强迫我在第三行中分配之前将32位值显式地投射到16位)?

< P>不。标准不强制编译器如何发出诊断。参见[定义诊断]:

属于实现的输出消息的实现定义子集的消息

它是警告还是错误取决于编译器。回答第二个问题,这似乎是一个质量问题。例如,GCC发出诊断信号:

g++ -std=c++11 -Wconversion test.cpp
test.cpp: In function ‘int main()’:
test.cpp:6:10: warning: conversion to ‘uint16_t {aka short unsigned int}’ from ‘uint32_t {aka unsigned int}’ may alter its value [-Wconversion]
 test16 = test32;

您可以尝试在Visual Studio中使用警告设置,也可以提交错误报告。

我倾向于同意后一种设置也应该为您提供警告。您可能想看看2017年的类型定义uint32和uint16的目的,看看是否有可能导致他们受到不同对待的原因。如果它们将def类型定义为unsigned long和unsigned short,但行为与直接使用这些类型不同,那么这可能是一个bug,需要报告。如果他们给别的东西打def。。。嗯,这可能是一个不同类型的bug,也应该报告。但是知道细节以便于报告它们对任何人阅读报告都是有帮助的。“C++编译器不应该给我错误而不是对这些方法中的任何一个警告”,因为C++标准允许缩小转换,编译器为什么会给这些错误提供错误?将警告视为错误,C++将被视为错误。它希望是,但它不是,主要是因为backcompat。因此警告而不是错误。@AlgirdasPreidžius-同意。通常,最好将警告视为错误,并根据具体情况禁用无法或不愿处理的警告。一再证明,警告毫无意义。有太多的程序员除非被迫,否则不会修复警告,这意味着在编译过程中,他们经常会在数英里的警告喷发中错过非常有效的警告。是的,当我将光标悬停在uint32\u t或uint16\u t上时,它们将typedef显示为unsigned long和unsigned short。感谢您确认这是一种奇怪的行为,而不仅仅是我对事情应该如何运作的误解。