我遇到了一些类似于以下内容的代码:
uint8_t* dataPtr = {0};
switch(index)
{
case 0:
dataPtr = (uint8_t[32])
{
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
}
break;
case 1:
dataPtr = (uint8_t[32])
{
0x43, 0x42, 0x41, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x22, 0x21, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x12, 0x31, 0x30, 0xAF, 0x27, 0x38, 0x89,
0x33, 0x32, 0x55, 0x30, 0xFF, 0xFF, 0x38, 0x89,
}
break;
依旧......
编写的代码似乎有效。我不明白内存是如何被破坏的。 dataPtr
的初始定义将其定义为指向具有未知大小的uint8_t
的空数组的指针。然后,它被转换为32 uint8_t
的静态数组并分配数据。
在初始定义期间,编译器如何知道为此变量分配多少内存?在运行时期间是否在堆栈上分配了这个内存?在编译期间的其他地方?
答案 0 :(得分:5)
这些是复合文字。 1999年修订版C中增加了一个特征。但是它们在这里的使用充满了未定义的行为。
(uint8_t[32])
{
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
0x33, 0x32, 0x31, 0x30, 0x29, 0x27, 0x38, 0x89,
}
以上将创建一个32 uint8_t
的匿名数组。 It's storage duration depends on the scope where it appears。并且由于它出现在交换机的块范围内,dataPtr
最终指向超出范围的对象,其生命周期已正式结束。
复合文字的值是初始化列表初始化的未命名对象的值。如果复合文字出现在函数体外,则该对象具有静态存储持续时间;否则,它具有与封闭块相关的自动存储持续时间。
答案 1 :(得分:2)
变量dataPtr
只是一个指针。它的大小是指针的大小。但是,您可以随意更改它指向的内容。
在程序开始时,它指向一个带有1个元素的常量数组。稍后,它被修改为指向具有32个元素的不同常量数组。在程序启动时,这些常量已经被分配(很可能只在内存的只读部分中)。
看起来像演员表的语法实际上是复合文字。