地址指针中的方括号是什么?
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];
这是未定义的行为,通过 flags
和 index
指针将 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_t
到 uint16_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;
}
我一直在搜索寻址指针中的方括号是什么,但我继续不理解它。以下是函数的行,其中“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];
这是未定义的行为,通过 flags
和 index
指针将 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_t
到 uint16_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;
}