This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/CCStudio-MSP:隐式类型转换并不总是很好

Guru**** 2039500 points
Other Parts Discussed in Thread: MSP430FR5989
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/600259/compiler-ccstudio-msp-implicit-type-conversion-not-always-work-well

部件号:CCStudio-MSP
主题中讨论的其他部件:MSP430FR5989

工具/软件:TI C/C++编译器

IDE:CCS 6.1 IDE/CS 7.1

编译器:TI v 4.4 .3/TI 16.9 v.1.LTS

测试程序如下所示:

----------------

INT MAIN ()

   无符号字符I;
   无符号长num_32;

   对于(i=0;i<50;+I)
   {
      num_32 = 0x8823 * i;
      DEBUG_SEND_STRING_l (&num_32,4);   //输出结果
   }
   返回0;
}
----------------

输出为:

-----------

00 00 00 00 00

23 88 00 00 00

46 10 00 00 00

69 98 00 00 00

8C 20 00 00 00

AF A8 00 00 00

.....

--------

但预期的结果是

--------

00 00 00 00 00

23 88 00 00 00

46 10 01 00

69 98 01 00

8C 20 02 00

AF A8 02 00

....

--------

如果我将表达式更改为"num_32 = 0x8823 *(unsigned long) i;",程序工作正常。

我认为这可能是因为编译器使隐式类型转换仅基于源操作数,而不考虑结果。

无符号整数类型可以同时包含0x8823和I,因此编译器将它们转换为无符号整数类型,但不认为num_32是无符号长型的数字,

我还在CodeBlocks 10.5 和Visual Studio 2005 SP1中对该程序进行了补充,该程序按预期运行。

如果它是编译器的错误,我希望它能得到修复。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    a unsigned integer type可以同时包含0x8823和i,因此编译器将它们转换为unsigned integer类型,但不认为num_32是unsigned long类型的数字,

    这是积分升级的预期行为; 请参见 How to Write Multiplies in C Code

    我还在CodeBlocks 10.5 和Visual Studio 2005 SP1中兼容此程序,该程序按预期运行。

    您没有说您在哪个TI器件上运行该程序, 但是,您可以猜测正在设备上运行的无符号int是16位,而在 Visual Studio中,无符号int至少是32位,这说明了行为的差异。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Chester Gillon 说:
    这是整体促销的预期行为;请参见 How to Write Multiplies Correctly in C Code[/QUOT]

    感谢您的建议。 我已经阅读了文档并了解 了TI编译器在类型转换中的行为。

    Chester Gillon 说:
    您没有说过运行程序的TI器件,而是猜测运行在无符号int为16位的器件上,而在 Visual Studio中,无符号int将至少为32位,这将解释行为的差异。[/QUOT]

    我的设备是MSP430FR5989,无符号int是16位。 但是,如果我在CodeBlocks 10.5 和Visual Studio 2005 SP1中运行下面的程序,我们可以看到“0x8823”和“i”都被转换为 无符号短整型,它们的长度为16位,但结果是32位,不会溢出。 在处理隐式类型转换时,TI编译器和其他编译器之间可能存在一些差异? 我认为CodeBlocks 10.5 和Visual Studio 2005 SP1的行为应该更好,因为它们可以防止类似这样的数据溢出。

    -----------------------

    INT MAIN ()

       无符号字符I;
       无符号长num_32;

       printf ("%d\r\n",sizeof (unsigned short int));

       对于(i=0;i<50;+I)
       {
           num_32 =(无符号短整型) 0x8823 *(无符号短整型) i;
           printf ("%lx ",num_32);   //输出结果
       }
       返回0;
    }

    ----------------

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您可以说其他编译器“更好”的唯一方法是,所有三个编译器上的sizeof(unsigned short int)都是相同的。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    MSP430上的"int"大小为16位。 Windows上"int"的大小为32位。 这使得无法在两个平台之间对"0x8823 * I"进行有意义的比较。

    在MSP430上,(unsigned short int) 0x8823 *(unsigned short int) i是一个未签名的16位操作;不允许编译器生成32位结果;这将违反C标准。

    在MSP430上,0x8823 * I生成一个带符号的16位操作,如果I >=2,则会溢出。 带符号整数算术溢出行为未定义。 编译器知道这一点,并相信程序员永远不会将程序置于如此糟糕的境地,因此优化器将利用此优势执行更积极的优化。 这些优化在代码片段中并不明显,但在其他地方很重要,因此编译器不会更改其有关签名乘法溢出的行为。