C指针,使用强制转换



我在我正在做的项目中偶然发现了一些代码,我想确保正确理解它。这里是:

uint16_t* tmp;
tmp = (uint16_t*) ((uint8_t*)getVariableAddress(variable) + offset);
tmp = (uint16_t*)((uint8_t*)tmp + otherOffset);
Set_Register((unsigned long) tmp[0]);
Set_OtherRegister((unsigned long) tmp[2]);

起初我在所有类型转换之间有点迷路,但我看到uint8_t*被用来每字节移动一个字节,并将偏移值添加到我们在tmp中放置的基址,这是让我感到困扰的第一部分。第二部分是在uint16_t*上使用[],对于这个,我完全不确定结果,有人愿意详细解释这一点吗?

感谢

我想如果我们重写一下代码会更容易看到发生了什么:

// We keep this as a `uint8_t *` so we can add offsets correctly.
uint8_t *base_address = (uint8_t *)getVariableAddress(variable);
// Add the offsets to the base address.
uint8_t *offsetted_address = base_address + offset + otherOffset;
// We want it as a uint16_t.
uint16_t *as_u16 = (uint16_t *)offsetted_address;
// We want to write the first register with the first `uint16_t` at `offsetted_address`, but `Set_Register` takes the value as `unsigned long`.
unsigned long first_u16 = as_u16[0];
Set_Register(first_u16);
// We want to write the other register with the third `uint16_t` at `offsetted_address`, but `Set_OtherRegister` takes the value as `unsigned long`.
unsigned long third_u16 = as_u16[2];
Set_OtherRegister(third_u16 );

我们知道我们感兴趣的值相对于getVariableAddress返回的地址有一个偏移。为了正确地计算该地址,我们将地址强制转换为uint8_t。如果我们保持uint16_t不变,我们的计算就会出错。想想看:

uint8_t *p = (uint8_t *)0x100;
printf("%pn", p + 1); // prints 0x101
uint16_t *q = (uint16_t *)0x200;
printf("%pn", q + 1); // prints 0x202

然后我们想要从我们刚刚计算的地址中读取第一个和第三个16位无符号整数,所以我们将其转换为uint16_t *并获得第一个([0])和第三个([2])整数。

当你使用诸如:

int var[5];
var[3] = 1;

当声明var时,它在内存中连续分配5个整数,var只获得指向这5个内存槽中的第一个的指针,本质上是一个int*

然后当你用var[3]访问它时,你告诉它访问第一个内存地址,偏移量是sizeof(int)的3倍。

在您的示例中,它正在做同样的事情,您正在获得指向tmp指向的第一个内存位置的指针,然后为其添加值的偏移

otherOffset以字节为单位,但tmpuint16_t *。如果地址计算为tmp + otherOffset,则将otherOffset视为uint16_t对象的数量而不是字节数来计算总和。因此,为了进行所需的计算,将tmp转换为uint8_t *。然后(uint8_t *) tmp + otherOffset以字节为单位进行计算。

同样,offset以字节为单位,getVariableAddress(variable)的类型可能不是指向字节/字符类型的指针(因为您没有向我们展示它的声明,我们不知道),因此强制转换确保以所需的单位(字节)进行算术运算。

uint16_t *的强制转换只是将算术运算的结果转换为所需的指针类型,以供以后使用。

tmp[0]tmp[2]是下标的普通用法。实际上,它们说,"有一个uint16_t数组,从tmp指向的位置开始。给我数组中索引为0或2的元素"形式上,tmp[i]被定义为*(tmp + i),表示将偏移量i添加到tmp上,然后对结果地址解引用。

最新更新