sizeof预处理字符串在MinGW与mikroC PRO for ARM的差异是否违规?
这是mikroC PRO for ARM的编译器实现缺陷,不符合C标准
首先明确结论:这不是正常的C语言平台差异,而是mikroC PRO for ARM编译器违反了C标准的规定。
C标准的明确规则
根据C标准,相邻的字符串字面量会被编译器自动拼接成一个单一的字符串字面量,这个字面量会自动包含一个\0终止符。sizeof运算符作用于字符串字面量时,返回的是包含该终止符在内的总字节数。
比如:
// 拼接后是"abcdef",sizeof返回7(6个字符+1个\0) sizeof("abc" "def") == 7;
在你的场景中:
__DATE__的格式是固定的"MMM DD YYYY",共11个字符__TIME__的格式是固定的"HH:MM:SS",共8个字符- 加上中间的空格,拼接后的字符串总字符数是
11+1+8=20,加上\0终止符,总长度应该是21。因此标准C中sizeof(SAVEFILECHECK_COMPILE_DATE)必须返回21。
mikroC PRO for ARM的问题
mikroC的行为明显矛盾:
- 它计算
sizeof(SAVEFILECHECK_COMPILE_DATE)和strA的长度时返回20,说明它错误地认为拼接后的字符串字面量不包含\0终止符 - 但
strB[] = SAVEFILECHECK_COMPILE_DATE却能初始化出长度为21的数组(包含\0),这说明编译器在处理数组初始化时又正确识别了终止符的存在
这种自相矛盾的行为属于编译器的实现缺陷,不符合C标准对字符串字面量和sizeof运算符的定义。
可行的修复方案
- 显式指定数组长度:因为
__DATE__ + 空格 + __TIME__的总字符数是固定20,直接定义数组长度为21(包含终止符):char strA[21]; - 用自动推导的数组作为参考:既然
strB能被正确初始化,你可以直接使用strB进行校验,或者用sizeof(strB)来定义strA的长度:char strB[] = SAVEFILECHECK_COMPILE_DATE; char strA[sizeof(strB)]; - 运行时计算长度:如果需要动态适配(虽然这里没必要),可以用
strlen(SAVEFILECHECK_COMPILE_DATE) + 1来获取正确长度,但注意这是运行时计算,会占用少量资源。
内容的提问来源于stack exchange,提问作者cFsichb
相关产品推荐
相关产品推荐

