地址指针中的方括号是什么?

What are for square brackets in an addressed-of pointer?

我一直在搜索寻址指针中的方括号是什么,但我继续不理解它。以下是函数的行,其中“id”变量是一个 uint32_t 指针,之前已作为参数传递。

#define LIST_STARTED (0x0001) /*defined out of the function*/
#define LIST_FIRST   (0x0002) /*defined out of the function*/

uint32_t *pointer = id;
uint16_t *flags = &((uint16_t *)pointer)[0];
uint16_t *index = &((uint16_t *)pointer)[1];
bool started = *flags & LIST_STARTED;
bool first   = *flags & LIST_FIRST;

if (!started){
    /* does something */
    *flags = MSEC_PRM_MGMT_LIST_STARTED;
    return true;
}
if (!first){
    /* does something */
    *flags |= MSEC_PRM_MGMT_LIST_FIRST;
    *index = 1;
    return true;
}
if (*index == final_index)
    /* does something */
    return false;

*index += 1;

我明白这个函数的逻辑是什么,但我不明白下面几行是做什么的。我把“所有”代码放在上面以防它对你有帮助。

uint16_t *flags = &((uint16_t *)pointer)[0];
uint16_t *index = &((uint16_t *)pointer)[1];

如果有人能帮助我,我将不胜感激! 谢谢!

我编辑说这个 C 代码在嵌入式系统中运行良好,我没有修改它,我只是观察它的行为。

以下代码尝试将 uint32_t 对象读取为两个 uint16_t 对象的数组:

uint32_t *id = ...;
uint32_t *pointer = id;
uint16_t *flags = &((uint16_t *)pointer)[0];
uint16_t *index = &((uint16_t *)pointer)[1];

这是未定义的行为,通过 flagsindex 指针将 uint32_t 对象读取为 2 个 uint16_t 对象,因为这违反了严格的别名规则。

正确的方法是:

uint16_t flags = *id; // The lowest order bits of id.
uint16_t index = *id >> 16; // The highest order bits of id.

在上述 uint32_tuint16_t 的赋值中,它截断了 id.

的最高位
uint32_t *pointer = id;
uint16_t *flags = &((uint16_t *)pointer)[0];

相当于。

uint32_t *pointer = id;
uint16_t *flags = (uint16_t *)pointer;

定义:

uint16_t *index = &((uint16_t *)pointer)[1];

相当于:

uint16_t *temp = (uint16_t *)pointer;
uint16_t *index = temp + 1;
//or
uint16_t *index = &temp[1];

这称为:指针双关,被认为是危险的且不可移植的。

您可以使用联合来进行安全的双关语(至少在使用 gcc 或其衍生物时)

typedef union
{
    uint64_t u64;
    uint32_t u32[2];
    uint16_t u16[4];
    uint8_t u8[8];
    struct
    {
        uint8_t n1: 4;
        uint8_t n2: 4;
    }u4[8];
}union_pune_t;


uint16_t foo16(uint32_t *p32)
{
    union_pune_t *d64 = (void *)p32;

    return d64 -> u16[1];
}

uint8_t foo8(uint32_t *p32)
{
    union_pune_t *d64 = (void *)p32;

    return d64 -> u8[5];
}

uint8_t foon4(uint32_t *p32)
{
    union_pune_t *d64 = (void *)p32;

    return d64 -> u4[9].n2;
}