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.

[参考译文] 编译器/ARM-CGT:与--strict_ansi 进行组合时可变参数宏会导致错误

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/930670/compiler-arm-cgt-variadic-macro-leads-to-error-when-comipling-with---strict_ansi

器件型号:ARM-CGT

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

我正在使用-c99进行编译、并使用可变参数的宏、该宏工作正常、符合预期(在实际硬件上进行了无数次测试)。

但是、目标是使用 -c99和-strict_ansi 进行编译。 但是、现在我在使用可变参数宏时遇到了错误:

错误#55-D:调用宏"get_macro"时参数太少 

ISO C99引入了可变参数宏、为什么会出现此错误? 使用此可变参数宏的频率很高、以至于局部抽吸不是一个选项、全局抽吸警告几乎不是一个好建议。

那么、如何解决这个问题呢?

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

    遗憾的是、我无法重现此问题。

    我不能要求提供典型的预处理测试用例、因为在预处理过程中会出现您的问题。  因此、如果您将问题缩小到更小的尺寸、我将不胜感激。  请记住、我只需要编译一个文件。  我不需要链接或运行。  请将文件放入 zip 文件、然后将其附加到下一篇帖子中。

    请准确地显示编译器看到的所有构建选项。  将其复制并粘贴到下一个帖子中。

    您使用哪个版本的编译器?

    谢谢、此致、

    乔治

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

    考虑以下代码:

    #define GET_MACRO (_1、_2、_3、name、...) 名称
    #define foo (...) get_macro (_va_args__、foo3、foo2、foo1)(_va_args__)
    
    int foo1 (int i){
    return i;
    }
    
    int foo2 (int i、int j){
    返回 i + j;
    }
    
    int foo3 (int i、int j、int k){
    返回 i + j + k;
    }
    
    
    int main (void)
    {
    int var = 0;
    var = foo (1);
    var += foo (1、2);
    var += foo (1、2、3);
    VAR_;
    返回0;
    } 

    这在 c99模式下编译正常:

    
    
    
    
    编译针对工程 varidad_macro 的配置调试**"C:\\ti\\ccs1000\\ccs\\utils\bin\\gmake"-k -j 8所有-O 构建文件:"../main.c"调用:ARM 编译器"C:/ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/bin/armcl -mv7R5 -code_state=32 -----proc 构建文件:"../main.c"调用:arm 编译器"cc_off-combe_display_example_display=-cn=vabi=-rom-cn-pg_ex-supervise_display-out-com-proc-proc-pg=-superval-ine-board-supervise_display-ine-proc-pg=-supervise_display-ine-board-cn=-cn=-overview-cn-overview-overview-overview-overview-overview=-/ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/include /test/ti-hercules-crc-examples/src/CCS_Projects/variadic_macro preproc_dependence="main.d_ra""./main.c"
    已完成构建:"./main.c"
    
    正在构建目标:"varidad_macro.out"
    调用:arm Linker "C
    :/ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/bin/armcl -mv7R5-code_state=32 -float_support=VFPv3d -c99 -varidad_macrobs"--display_zh-ine-intrab-code_display_macrobs-"-code_display_macrobule-ex-rom_zh-ine-control-rom_info-display_macrobi-display_macrobi-display_macrobi-display_zh-ine-ine_display_macrobi-display_info-ine_display_macrobi-display_ine_display_macrobi-display_info-code_display_macrobi-display-rom-rom-rom-rom-rom-rom-rom-rom-rom-rom-rom-rom-rom-ine_display_infot_infot_code_display_in /ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/include /ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/lib rom_model --be32 -o "varidad_macro.out""./main.obj"-llibc.a
    
    警告#10247-D:创建不带段规范
    的输出段".text"已完成构建目标:"varidad_macro.out"
    
    
    ****编译已完成**** 

    现在添加--strict_ansi

    
    
    
    
    编译针对工程 varidad_macro 的配置调试**"C:\\ti\\ccs1000\\ccs\\utils\bin\\gmake"-k -j 8所有-O 构建文件:"../main.c"调用:ARM 编译器"C:/ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/bin/armcl -mv7R5 -code_state=32 ---proc-pred_example.compr-cn=vat_rom-cn=-proc-intrab-pred_supervisorit_rom-cn=-overview-cn=-overview-overview-overview-overview=-overview-overview-overview-overview=-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview-overview=-overview-overview-overview-overview-/ti/ccs1000/ccs/tools/compiler/ti-cgt-arm_20.2.0.LTS/include /test/ti-hercules-crc-examples/src/CCS_Projects/variadic_macro strict_ansi "../main.c"
    
    >>编译失败
    subdir_rules.mk:9:目标'main.obj
    
    
    的 obj 失败"../main.c",第20行:错误#55-D:调用宏"get_macro"时的参数太少。在编译"../main.c"时检测到错误。gmake:***
    不是所有的目标'gmake'错误。
    
    ****构建完成**** 

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

    C99 ANSI 标准在第6.10.3节中说明了如何调用接受可变数量参数的宏...

    调用中的参数应多于宏定义中的参数(不包括...)。

    宏调用 foo(1)被替换为...

    get_macro (1、foo3、foo2、foo1)(1) 

    这是4个参数。  为避免违反标准中的上述句子、应该有5个或更多。  因此是诊断。

    我知道为什么您会犹豫抑制编译器诊断。  但我认为这是最好的前进方式。  在您的第一个帖子中、此诊断的文本包括#55-D  这意味着此诊断的 ID 号为55、是任意的。  由于它是可自由选择的、因此可以抑制它。  有几种不同的方法可以抑制它 、一种方法是使用构建选项--diag_suppress=55。   

    BTW、上述 C99 ANSI 标准的链接不是官方标准、而是最新的公开发布版本。  对于大多数用途、包括这个、它足够接近。

    谢谢、此致、

    乔治

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢 George 的出色解释。 但是、我想知道这一修复是否不够:
    伪参数为 append、且函数为 dummy 对于编译器来说是空的、应将其优化、并且不应出现运行时性能下降。
    或者我是否遗漏了任何内容、为什么这种修复是一个坏主意?
    #define GET_MACRO (_1、_2、_3、name、...) 名称
    #define foo (...) get_macro (_va_args__、foo3、foo2、foo1、dummy)(_va_args__)
    void dummy (void){}
    int foo1 (int i){
    return i;
    }
    int foo2 (int i、int j){
    返回 i + j;
    }
    int foo3 (int i、int j、int k){
    返回 i + j + k;
    }
    
    int main (void)
    {
    int var = 0;
    var = foo (1);
    var += foo (1、2);
    var += foo (1、2、3);
    VAR_;
    返回0;
    } 

    因此、我不需要抑制编译器警告。

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

    [报价用户="user6135372"]我是否缺少任何内容

    否  这似乎是一个合理的修复。

    user6135372 说:
    函数为空,编译器应将其优化,并且不应出现运行时性能下降的情况。

    不会生成对虚拟函数的调用。  但是、它仍占用目标文件中的空间。  您可以选择忽略这一小部分浪费的空间。  如果您想确定虚拟函数已被删除、则使用编译器选项 -gen_func_subsections 进行编译。  这会使每个函数都放置在其自己的子段中。  链接器会删除任何未引用的此类子段。  另一种考虑方法是:如果未调用其自身段中的函数、则会将其删除。  但是、在某些情况 下、使用-gen_func_subsections 会导致存储器使用总量增加。  了解的唯一方法是进行实验。

    谢谢、此致、

    乔治

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

    明白了、再次感谢您的完美回答!