C 零填充字符串提供警告,但无论如何都有效

C 零填充字符串提供警告,但无论如何都有效,c,embedded,C,Embedded,TL;博士: 编译器发出警告。该行为未定义 但是由于未定义的行为对公司有利,因此试图找到一个坚实的理由来纠正它(更改100行代码,需要说服经理) sprintf警告 与“%s”gnu_printf格式一起使用的“0”标志 根据SO问题/答案,此行为未定义 但是在带有SW4STM32工具链()的armgcc中,根据需要填充零 MCVE 对于STM32 下面的代码是针对嵌入式系统的,要编译它,需要提供工具链。剩下的文件请转到 上述代码将通过UART传输数据,然后使用PC-USB收发器读取。上述代

TL;博士

  • 编译器发出警告。该行为未定义
  • 但是由于
    未定义的行为对公司有利,因此试图找到一个坚实的理由来纠正它(更改100行代码,需要说服经理)
sprintf警告

与“%s”gnu_printf格式一起使用的“0”标志

根据SO问题/答案,此行为未定义

但是在带有
SW4STM32
工具链()的armgcc中,根据需要填充零

MCVE

  • 对于STM32
  • 下面的代码是针对嵌入式系统的,要编译它,需要提供工具链。剩下的文件请转到

    上述代码将通过UART传输数据,然后使用PC-USB收发器读取。上述代码的输出为

    #0000000001,0000000002,00000000000000000003,000000000000000000000000000000000000000000000000000000000004
    
    正如您所看到的,即使发出了警告,代码还是按照程序员的要求执行/表现

    这是一个遗留代码,此错误已写入许多地方。因此,我要修正它,必须修正许多行。但是由于代码按预期执行,经理不想更改代码

    问题

    • 代码的行为符合程序员的预期,即使它是
      未定义的
      。这种未定义的行为将来会改变吗
    • 我可以用什么理由让他们纠正这个错误
        我不会更改代码,因为当前的工具链会产生所需的行为(永远不会更改正在运行的系统)

        但是您可以在某个地方为当前版本的工具链添加一个锁。
        差不多

        #if !defined(__ARMCC_VERSION) || (__ARMCC_VERSION != 4711)
        #error DON'T CHANGE THE TOOLCHAIN, check if 'sprintf("%010s", "1" )' still works!
        #endif
        

        为了确保您的工具链不会出现未定义的行为,您应该查看sprintf.c/vsprintf.c源代码。

        未定义的行为就是未定义的行为应用程序可以在UB之后执行任何操作。它可能从某个位置的RAM中读取一个值,并使用该值确定是否对字符串进行零填充,或者它可以正确地对字符串进行零填充,但决定完全破坏所有堆栈帧。或者在不相关的代码区域将减法改为加法

        未定义的行为是未定义的。任何事情都有可能发生

        有人指出,“但由于未定义的行为对公司有利……”这似乎是可行的。对于给定的一组启动条件。对于当时存在的代码库。只要你在任何地方做了一次改变,所有的赌注都会被取消


        话虽如此,最有可能的情况是编译器选择了定义行为,而该行为恰好是您所期望的。在这种情况下,杰布的回答可能对你有用。但就我个人而言,我永远不会依赖未定义的行为,不管副作用看起来多么无害。

        你能试着创建一个新的方法来展示给我们看吗?最好包含复制问题所需的最简单的代码(例如,
        #include int main(void){/*printf引起警告,仅此而已,使用最简单的格式字符串*/}
        )。还有几点:当您指空终止符时,您会说“NULL”。这些在语义上非常不同
        NULL
        是一个NULL指针,不应与字符串NULL终止符(字符
        '\0'
        )混淆。您还可以在一个实例中将
        char
        数组强制转换为
        char*
        。不需要该强制转换,数组将衰减为指向其第一个元素(类型为
        char*
        )的指针。这里最大的问题是嵌入式系统中存在stdio.h。我相信这将是一个更好的MCVE,关键词是最小化:
        charbuff[100];sprintf(buff,“%010s”,“1”)。但无论如何:由于这是遗留代码,可能没有单元测试,它目前正在工作,您的经理不希望您更改它,我相信答案是明确的:不要修改它。在可能的情况下,你将无法获得修复此问题的许可:确保你收集了证据,证明代码最终崩溃时这不是你的错。这是一个很好的答案。它现在可以工作,但以后可能会崩溃。很明显,这段遗留代码中正在进行更改,因此,如果将来可能会失败,为什么要冒险呢。非常感谢。
        
        #if !defined(__ARMCC_VERSION) || (__ARMCC_VERSION != 4711)
        #error DON'T CHANGE THE TOOLCHAIN, check if 'sprintf("%010s", "1" )' still works!
        #endif