sizeof("string") 的正确输出是什么?

问题描述 投票:0回答:2

在微控制器上,为了避免从以前的固件版本加载设置,我还存储编译时间,在加载时检查。

微控制器项目是使用 MikroElektronika'mikroC PRO for ARM' 构建的。

为了更容易调试,我在 PC 上用 minGW 编写了代码,左右检查后将其放入 microC 中。

使用该检查的代码无法正常工作。经过一晚令人沮丧的调试后,我发现 sizeof("...") 在两个平台上返回不同的值,并导致缓冲区溢出成为罪魁祸首。

但现在我不知道是谁的错。

要重新解决问题,请使用以下代码:

#define SAVEFILECHECK_COMPILE_DATE __DATE__ " " __TIME__

char strA[sizeof(SAVEFILECHECK_COMPILE_DATE)];
char strB[] = SAVEFILECHECK_COMPILE_DATE;

printf("sizeof(#def): %d\n", (int)sizeof(SAVEFILECHECK_COMPILE_DATE));
printf("sizeof(strA): %d\n", (int)sizeof(strA));
printf("sizeof(strB): %d\n", (int)sizeof(strB));

在 MinGW 上它返回(如预期):

sizeof(#def): 21
sizeof(strA): 21
sizeof(strB): 21

在“mikroC PRO for ARM”上,它返回:

sizeof(#def): 20
sizeof(strA): 20
sizeof(strB): 21

这种差异导致了缓冲区溢出。 (覆盖指针的字节零,哎呀!) 21 是我期望的答案,20 个字符和 ' ' 终止符。 这是 C 中“视情况而定”的事情之一,还是 sizeof 运算符的行为遭到破坏?

c string language-lawyer sizeof mikroc
2个回答
0
投票

这一切都是100%标准化的。 C17 6.10.8.1:

__DATE__
预处理翻译单元的翻译日期:
"Mmm dd yyyy"

形式的字符串文字 ...
__TIME__
预处理翻译单元的翻译时间:字符串文字 形式
"hh:mm:ss"

  • “嗯 dd yyyy”= 11
  • “时:分:秒”= 8
  • " "
    (用于字符串文字连接的空格)= 1
  • 空终止 = 1

11 + 8 + 1 + 1 = 21

至于

sizeof
,字符串文字是一个数组。每当您将声明的数组传递给
sizeof
时,该数组都不会“衰减”为指向第一个元素的指针,因此
sizeof
将报告数组的大小(以字节为单位)。对于字符串文字,这包括 null 终止符。

因此,mikroC PRO 似乎不合格/存在缺陷。肯定有很多有问题的嵌入式系统编译器。


0
投票
#include <stdio.h>

int main(){
    printf("%zu\n", sizeof("aa"));
}

有趣的是,在这种情况下,

"aa"
并没有衰减为指针,而是充当字符数组。由于数组有 3 个元素(包括零终止符),因此输出为 3。

这定义了字符串(字符数组)

#include <stdio.h>

#define SAVEFILECHECK_COMPILE_DATE __DATE__ " " __TIME__

int main(){
    printf("%zu\n", sizeof(SAVEFILECHECK_COMPILE_DATE));
}

每次编译的结果都不一样,因为

__DATE__
__TIME__

我目前的结果是21,但可能会改变。

对于 C++ 也同样有效。

© www.soinside.com 2019 - 2024. All rights reserved.