将指针强制转换为固定大小的数组

时间:2017-04-06 20:25:49

标签: c arrays pointers

我遇到了一些类似于以下内容的代码:

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的静态数组并分配数据。

在初始定义期间,编译器如何知道为此变量分配多少内存?在运行时期间是否在堆栈上分配了这个内存?在编译期间的其他地方?

2 个答案:

答案 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最终指向超出范围的对象,其生命周期已正式结束。

或标准[C11 N1570 6.5.2.5p5]

  

复合文字的值是初始化列表初始化的未命名对象的值。如果复合文字出现在函数体外,则该对象具有静态存储持续时间;否则,它具有与封闭块相关的自动存储持续时间。

答案 1 :(得分:2)

变量dataPtr只是一个指针。它的大小是指针的大小。但是,您可以随意更改它指向的内容。

在程序开始时,它指向一个带有1个元素的常量数组。稍后,它被修改为指向具有32个元素的不同常量数组。在程序启动时,这些常量已经被分配(很可能只在内存的只读部分中)。

看起来像演员表的语法实际上是复合文字