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.

[参考译文] 编译器/MSP-CGT:错误:指向 void 的指针上的算术在比较(和优化)中生成错误的代码

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

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/927303/compiler-msp-cgt-bug-arithmetic-on-pointer-to-void-produces-incorrect-code-in-comparisons-and-optimisations

器件型号:MSP-CGT

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

如果我有以下代码

extern unsigned char __heap[512];

#define MID ((void *)_heap + 256)
#define end (((void *)_heap + 512)

void func (void)
{
void *ptr =结束;
执行{
*(unsigned char *) ptr = 1;
ptr -= 32;
} while (ptr > MID);
} 

我获得有关 void 指针算术的可接受警告、但生成的代码在所有优化级别下都不正确。

在 opt_level=0下、我得到以下结果:

;** 9--- ptr =&_heap+512;
.dwpsn 文件"ptrloop.c"、行9、列15、is_stmt、ISA 0
MOV.W #_heap+512、R15 ;[]|9|
;*------------------------------------------------------- *
;*开始循环$C$L1
;*
;*循环源代码行 :10
;*循环右括号源行:13
;*已知最小循环计数 :1
;*已知最大行程计数 :4294967295
;*已知最大行程计数因子 :1
;*-------------------------------------------------------- *
$C$L1:
;**--- G2:
;** 11 ---------------- *(unsigned char *) ptr = 1U;
.dwpsn 文件"ptrloop.c"、行11、列9、is_stmt、ISA 0
MOV.B 1、0 (R15) ;[]|11|
;** 13----- 如果(ptr -= 32)>&_heap)转至 G2;
.dwpsn 文件"ptrloop.c"、行13、列14、is_stmt、ISA 0
低于 W #32、R15 ;[]|13|
CMP.W #_heap+1、R15 ;[]|13|
JHS $C$L1 ;[]|13|
;[]|13|
;** ------------ 返回;

您可以看到、`与`_heap+1`而不是`_heap+257进行比较。

在 opt_level=4下、我得到以下结果:

MOV.W #_heap+512、R15 ;[]|9|
;** ------------ #pragma MUST_ITERATE (16、16、16)
;** ------------ #pragma LOOP_FLAGS (0U)
;** ------------ L$1 = 16;
MOV.W #16、r14 ;[];*----
------------------------------------------------------ *
;*开始循环$C$L1
;*
;*循环源代码行 :10
;*循环右括号源行:13
;*已知最小循环计数 :16
;*已知最大行程计数 :16
;*已知最大行程计数因子 :16
;*---------------------------------------------------------- *
$C$L1:
;**--- G2:
;** 11 ---------------- *(unsigned char *) ptr = 1U;
.dwpsn 文件"ptrloop.c"、行11、列9、is_stmt、ISA 0
MOV.B 1、0 (R15) ;[]|11|
;** 13----- ptr -= 32;
.dwpsn 文件"ptrloop.c"、行13、列14、is_stmt、ISA 0
低于 W #32、R15 ;[]|13|
;** 13------------ 如果(L$1 = L$1-1)转至 G2;
低于 W 1、r14 ;[]|13|
JNE $C$L1 ;[]|13|
;[]|13|
;** ------------ 返回;

您可以看到循环运行16次、其中循环应该只运行8。

根据我可以得出的结论、如果将 void 指针算术的结果存储在比较中、就不会有问题。  这应该被修复、否则、void 指针算术警告应该被更改为一个错误。

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

    根据添加剂操作员章节(7.6.2)中的 Harbison 和 Steele:"p [a pointer]为函数指针或具有 void 类型*无效。"

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

    感谢您将此问题通知我们并提供简要的测试案例。  我可以重现相同的结果。  我提交了 EXT_EP-9941条目 以进行调查。  欢迎您使用我签名中的以下链接进行操作。

    Keith Barkley 正确地指出、未定义 void 指针的数学运算或比较运算。  也就是说、许多编译器、包括 TI MSP430编译器、通过假装它指向 char 而不是 void 来处理它。

    Parakleta 说:
    或者,否则应将 void 指针算术警告更改为错误。

    许多警告诊断、包括此诊断、都可以更改为编译器命令行上的错误。  添加编译器选项--display_error_number、编译器会在消息中显示诊断号。

    % cl430 --opt_level=4 -s -vmspx --display_error_number file.c
    "file.c",第8行:警告#1219-D:void 指针上的算术或函数类型
    "file.c",第11行:警告#1219-D:void 指针上的算术或函数类型
    "file.c",第12行:void 指针上的算术或 void 指针 

    使用选项--diag_error=number 将具有该数字的诊断作为错误处理。

    % cl430 --opt_level=4 -s -vmspx --display_error_number --diag_error=1219 file.c
    "file.c",第8行:错误#1219-D:void 指针上的算术或函数类型
    "file.c",第11行:错误#1219-D:void 指针上的算术或函数类型
    "1219-c",错误#1219-D: 在
    "file.c"编译中检测到的 void 指针或函数类型3错误的算术。
    
    >>编译失败 

    谢谢、此致、

    乔治

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

    Keith 很正确、C 标准不允许对要作废的指针进行指针算术。

    George 说得对、尽管如此、TI 编译器仍在宽松模式下支持这种类似 GCC 的扩展。

    此测试案例演示了一个错误、该错误将最终修复。

    同时、权变措施是将所有"void*"指针更改为"unsigned char *"指针、这将具有在严格 ANSI 模式下允许的额外好处。