为什么sizeof(无符号双精度)等于4?

sas*_*alm 71 c++ visual-studio-2010

我的一位同事询问是否有未签名的双,我说没有,但我仍然检查它,这在Microsoft Visual C++ 2010中编译:

unsigned double a;
double b;
printf("size_a=%d size_b=%d", (int) sizeof(a), (int) sizeof(b));
Run Code Online (Sandbox Code Playgroud)

它输出size_a=4 size_b=8.也就是说,四个字节unsigned double,和八个字节double.

Cyg*_*sX1 141

unsigned double是无效的.在MSVC中也是如此.在MSCV 2010中编译上述代码并启用警告时,您将获得:

warning C4076: 'unsigned' : can not be used with type 'double'

编译器实际上忽略 doubleunsigned,a实际上是一个unsigned int.

如果您尝试以下方法:

unsigned double a = 1.0;
Run Code Online (Sandbox Code Playgroud)

你实际上得到两个警告:

warning C4076: 'unsigned' : can not be used with type 'double'
warning C4244: 'initializing' : conversion from 'double' to 'unsigned int', possible loss of data
Run Code Online (Sandbox Code Playgroud)

有趣的是,MSDN中没有针对VS2010的C4076警告.它仅适用于VS2005和VS2008.

  • @PeteBecker不傻.通常会针对过去导致错误的问题发出警告.高中或以上的人不会对+ vs*优先级感到困惑; 对于&& vs ||,同样不能说.在我学习形式逻辑之前,我正在编程(并且对它们的优先级感到困惑). (23认同)
  • @PeteBecker - 我理解并同意你关于这个警告并不是一个警告的观点.但是,对于"专业程序员"而言,更容易理解没有括号的代码行是完全错误的.我已经是一名专业程序员已有15年,并且知道优先规则.您的示例中的两行代码对我来说同样清楚.添加括号以便澄清(就像数学家一样)并不会让我更难阅读和理解. (16认同)
  • @PeteBecker欢迎您禁用警告并告诉编程团队的人员他们必须全心全意地学习优先级.这真的是你的选择,假设你无论在哪里工作都能拥有那种力量.但实际情况是,这是一个bug的来源,并将继续成为bug的来源,所以不要把警告称为愚蠢. (14认同)
  • @PeteBecker - return(a || b && c <d + e*f + ++ g - h--); 这里也不需要parens.这真的和非最小版本一样清晰吗?Reductio ad absurdum.不能与理论家争论 - 我出局了. (10认同)
  • @PeteBecker括号实际上会导致任何问题吗?编译时,他们还没有得到优化吗?如果它们没有引起问题,甚至对编译代码没有任何影响,那么他们所做的只是让人们阅读代码更清楚,这是好事,不是吗? (9认同)
  • @satuon我敢打赌,一个顽固的MSVC开发人员有一个庞大的代码库,他们认为`unsigned double`是一个东西然后,当他们意识到它不是时,他们不想破坏他们的代码. (7认同)
  • @sftrabbit考虑到他们使用无符号整数作为浮点类型,人们不得不想知道他们的代码库是如何工作的. (7认同)
  • 如果你写`if(a = 5)`而不是`if(a == 5)`,你还需要一个警告,如果你认为它是一个赋值,你需要一个额外的括号来摆脱警告.需要它吗?不.但是,即使在了解`=`和`==`之间的区别的专业程序员中,它也是一个公共的错误来源. (6认同)
  • @MattFellows - 它取决于你添加括号的位置.`<G>`.如果你改变了'a && b || c && d`到`(a && b)|| (c && d)`他们不改变代码的含义.然而,它们确实使专业程序员更难阅读,因为它们表明代码正在做一些与众不同的事情; 否则他们不会在那里.混合优先级是初学者的错误; 全面建议告诉初学者添加括号只会使问题复杂化. (5认同)
  • @SebastianRedl - 抱歉,但我不同意程序员必须受到保护,免受他们自己的误解.如果您不知道如何在不添加不必要的括号的情况下编写逻辑表达式,请花时间学习它.添加括号的警告提供了不好的建议. (4认同)
  • @CramerTV - 在早期的一个问题中解释SO:`return((a <b)?(x):((c <d)?(y):(z)));`这些括号中没有一个是需要.这**真的**和最小版本一样清晰吗? (4认同)
  • @SebastianRedl - 再次:警告说**添加括号**.这是**糟糕的建议**; 编写正确的逻辑表达式并不难,学习如何正确使用该语言比应用黑客以避免学习要好得多.至于我工作的地方,不幸的是,在编写标准库时,管理这样的警告是一件非常令人头痛的问题.此警告的效果是**库代码中需要**括号. (3认同)
  • 为什么这不是我想知道的错误?! (2认同)
  • 在VS2010中,如果在"输出"窗格中选择警告并按F1,则会转到[2010年警告文档](http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN -US&K = K%28C4076%29; k%28VS.OUTPUT%29; k%28DevLang-%22C%2B%2B%22%29&RD =真). (2认同)
  • 哇.好吧,当你的小组不是一堆代数人时(虽然有些代数),使用括号来清楚.并且`&&`优先于`||`因为`&&'是乘法的:它有乘法零(假)和乘法同一性(真); 而`||`是附加的,因为它具有附加的身份(假). (2认同)

Cli*_*ord 26

如果您将警告级别设置得更高(我的测试中为/ W3),您将收到相应的警告:

警告C4076:'unsigned':不能与'double'类型一起使用

如果您随后使用调试器检查变量,则一切都变得清晰:

在此输入图像描述

你可以看到变量实际上是一个 unsigned int


Jos*_*eld 24

结合unsigneddouble在声明说明顺序无效C++.这必须是某种MSVC扩展(或bug).

作为一般规则,最多一个类型说明符被允许在完全DECL说明符-SEQ声明的或在一个类型说明符序列尾随类型说明符-SEQ.此规则的唯一例外情况如下:

  • const 可以与除自身之外的任何类型说明符组合使用.
  • volatile 可以与除自身之外的任何类型说明符组合使用.
  • signedunsigned可以结合char,long,short,或int.
  • short或者long可以结合使用int.
  • long可以结合使用double.
  • long可以结合使用long.

  • +1我不知道一些疯子@ MS甚至考虑使浮点无符号.我敢肯定它背后有一个原因,我不能认为它是一个好的 (5认同)