问题描述
我一直在寻找寻址指针中的方括号,但是我仍然不理解它。下面是函数的各行,其中“ 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];
这是未定义的行为,无法通过uint32_t
和uint16_t
指针将flags
对象读取为2个index
对象,因为这违反了严格的别名规则。
正确的方法是:
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
的最高位。
zonecfg -z cmovel-pf01 info
zonecfg can only be run from the global zone.
它等效于
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];
这称为:指针修剪,它被认为是危险的并且不可移植。
您可以使用联合进行安全修剪(至少在使用gcc或其衍生物时)
uint16_t *temp = (uint16_t *)pointer;
uint16_t *index = temp + 1;
//or
uint16_t *index = &temp[1];