在 C++ 中,以下两个声明是否等效?
static volatile uint16_t *ADCReadings = (uint16_t[64]){0};
或者static volatile uint16_t ADCReadings[64] = {0};
我正在为 AVR 上的 ISR 内部和外部使用的缓冲区保留空间。但是,虽然这会很有趣,但我不是在这里想知道这是否是最好的方法 - 我想知道这两个声明之间的区别(如果有的话)是什么,以便我能更好地理解这一点.我确实知道这两个不同的声明会产生不同大小的二进制文件,因此编译器似乎对它们的处理方式不同。
最佳答案
不。(uint16_t[64]){0}
是一个临时数组(复合文字*),如果你尝试编译第一行,你会得到一个不言自明的警告/错误:
所以,在第一行 ADCReadings
变成了一个悬空指针。将其用作指向缓冲区的指针会调用未定义的行为。
Gcc 手册 reads :
在这种情况下,Gcc 和 Clang 不会产生警告/错误。 Gcc 手册进一步写道:
所以似乎在全局范围内 ADCReadings
不会悬空。
在第一种情况下,复合文字数组进入 .bss
部分,ADCReadings
进入 .data
部分:
0000000000004040 l O .bss 0000000000000080 ._0
0000000000004010 g O .data 0000000000000008 ADCReadings
ADCReadings
是指向 ._0
的指针。第二种情况,
ADCReadings
直接进入.bss
:0000000000004040 g O .bss 0000000000000080 ADCReadings
这也转化为 ADCReadings
的使用方式。下面的简单函数:uint16_t* foo() {
return ADCReadings;
}
编译成:push rbp
mov rbp,rsp
mov rax,QWORD PTR [rip+0x2ed8] # 4010 <ADCReadings>
pop rbp
ret
和push rbp
mov rbp,rsp
lea rax,[rip+0x2f08] # 4040 <ADCReadings>
pop rbp
ret
* Compound literals 不是标准 C++ 的一部分,一些编译器(Gcc、Clang)允许它们作为扩展。
关于C++ 静态数组初始化 : does inline initialization reserve space?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63067409/