C 零填充字符串提供警告,但无论如何都有效
TL;博士:C 零填充字符串提供警告,但无论如何都有效,c,embedded,C,Embedded,TL;博士: 编译器发出警告。该行为未定义 但是由于未定义的行为对公司有利,因此试图找到一个坚实的理由来纠正它(更改100行代码,需要说服经理) sprintf警告 与“%s”gnu_printf格式一起使用的“0”标志 根据SO问题/答案,此行为未定义 但是在带有SW4STM32工具链()的armgcc中,根据需要填充零 MCVE 对于STM32 下面的代码是针对嵌入式系统的,要编译它,需要提供工具链。剩下的文件请转到 上述代码将通过UART传输数据,然后使用PC-USB收发器读取。上述代
- 编译器发出警告。该行为未定义
- 但是由于
未定义的行为对公司有利,因此试图找到一个坚实的理由来纠正它(更改100行代码,需要说服经理)
SW4STM32
工具链()的armgcc中,根据需要填充零
MCVE
#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中读取一个值,并使用该值确定是否对字符串进行零填充,或者它可以正确地对字符串进行零填充,但决定完全破坏所有堆栈帧。或者在不相关的代码区域将减法改为加法 未定义的行为是未定义的。任何事情都有可能发生 有人指出,“但由于未定义的行为对公司有利……”这似乎是可行的。对于给定的一组启动条件。对于当时存在的代码库。只要你在任何地方做了一次改变,所有的赌注都会被取消
话虽如此,最有可能的情况是编译器选择了定义行为,而该行为恰好是您所期望的。在这种情况下,杰布的回答可能对你有用。但就我个人而言,我永远不会依赖未定义的行为,不管副作用看起来多么无害。你能试着创建一个新的方法来展示给我们看吗?最好包含复制问题所需的最简单的代码(例如,
)。还有几点:当您指空终止符时,您会说“NULL”。这些在语义上非常不同#include int main(void){/*printf引起警告,仅此而已,使用最简单的格式字符串*/}
是一个NULL指针,不应与字符串NULL终止符(字符NULL
)混淆。您还可以在一个实例中将'\0'
数组强制转换为char
。不需要该强制转换,数组将衰减为指向其第一个元素(类型为char*
)的指针。这里最大的问题是嵌入式系统中存在stdio.h。我相信这将是一个更好的MCVE,关键词是最小化:char*
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