值加减,别忘可能是个指针运算

本文分析了DSPPCI驱动中的一段关键代码,详细解释了为什么在进行寄存器写入操作时,需要对TI_HSR进行除以4的操作。通过对指针运算的理解,揭示了该操作背后的原理。

在做dsp pci驱动时,有一句:

WRITE_REGISTER_ULONG((PULONG) (pdx->base[TI_OPREGS] + (TI_HSR/4)), TI_DISABLE);

TI_HSR 做了除以4,感觉不解,就把除以4去掉,运行。。。毫无意外的蓝屏了

pdx->base[TI_OPREGS] + (TI_HSR/4)

检测了它的值,发现和 pdx->base[TI_OPREGS]与TI_HSR的值相加结果一样。

感到很疑惑,后来看了pdx->base[TI_OPREGS]它的类型是PULONG,即无符号长整型数指针。

上述代码属于指针运算了,对于PULONG类型,加1,相当于在数值上加四。

 

 

<think> 我们参考了多个关于指针加减运算的引用资料,现在来总结指针加减运算的实质。 根据引用[1]:指针加减法不是简单的数运算,而是基于数据类型的地址运算。 引用[3]和[4]通过示例代码说明,指针加减运算的结果与指针所指向的数据类型的大小(即类型长度)有关。例如,int指针加1,实际地址增加4(因为int通常占4字节),double指针加1,实际地址增加8(double通常占8字节)。 引用[2]指出,指针指针的绝对是两个指针之间的元素个数(前提是两个指针指向同一个空间)。 引用[5]进一步说明,不同维度的数组和指针加减运算时移动的字节数不同,因为它们的存储单元大小不同。 因此,指针加减运算的实质是:指针加减运算是以指针所指向的数据类型的大小为单位进行地址的移动。 具体来说: 1. 指针加法:ptr + n 的结果是向后(地址增加的方向)移动 n 个数据类型大小的位置,即新地址 = 当前地址 + n * sizeof(数据类型)。 2. 指针减法:ptr - n 的结果是向前(地址减少的方向)移动 n 个数据类型大小的位置,即新地址 = 当前地址 - n * sizeof(数据类型)。 3. 两个指针相减:得到的是两个指针之间相差的元素个数,即 (ptr2 - ptr1) 的结果等于 (地址差) / sizeof(数据类型),前提是这两个指针指向同一个数组(或同一块连续内存空间)。 另外,指针的比较运算(如==, !=, >, <等)也是基于地址的大小比较。 我们通过一个例子来说明: int arr[5] = {10,20,30,40,50}; int *p1 = &arr[0]; // 假设地址为0x1000 int *p2 = p1 + 1; // 实际地址为0x1004(因为int占4字节),指向arr[1] int *p3 = p1 + 2; // 地址为0x1008,指向arr[2] 则: p2 - p1 = 1 (因为它们之间相差1个元素) p3 - p1 = 2 (相差2个元素) 注意:指针加减运算时,移动的单位是数据类型的长度,而不是1个字节。 因此,指针运算的本质是地址的运算,但以数据类型的大小为基本单位。 </think> ### 指针加减运算的实质 指针加减运算的本质是 **基于数据类型的地址偏移计算**,而非简单的数加减。核心要点如下: 1. **运算单位由数据类型决定** 指针加减整数 `n` 时,实际地址偏移量为: $$ \text{新地址} = \text{原地址} \pm n \times \text{sizeof(数据类型)} $$ 例如: - `int* ptr + 1`:地址增加 `4` 字节(`sizeof(int)` 通常为 4)[^1][^4] - `double* ptr + 1`:地址增加 `8` 字节(`sizeof(double)` 通常为 8)[^3] ```c int arr[3] = {10, 20, 30}; int *p = arr; // p 指向 arr[0](地址 0x1000) p = p + 1; // 实际地址变为 0x1004(偏移 4 字节) ``` 2. **指针指针:计算元素间隔** 两个同类型指针相减,结果为它们之间的 **元素个数**: $$ \text{元素个数} = \frac{\text{地址差}}{\text{sizeof(数据类型)}} $$ 例如: ```c int arr[5] = {0}; int *p1 = &arr[0]; // 地址 0x1000 int *p2 = &arr[3]; // 地址 0x100C int n = p2 - p1; // n = (0x100C - 0x1000)/4 = 3 ``` 前提是两指针指向 **同一连续内存空间**(如数组)[^2][^5]。 3. **运算的约束条件** - **有效性**:加减后的地址必须指向合法内存(如数组范围内)[^1] - **类型一致**:指针指针要求同类型,否则行为未定义[^2] - **维度影响**:多维数组的指针运算单位由元素类型决定(如 `int[][4]` 中 `+1` 偏移 `4×sizeof(int)` 字节)[^5] ### 底层原理 指针存储的是内存地址(整数),但编译器会根据其类型解释运算: - **加法 `ptr + n`**:编译器转换为 `(char*)ptr + n * sizeof(*ptr)` - **减法 `ptr1 - ptr2`**:编译器转换为 `((char*)ptr1 - (char*)ptr2) / sizeof(*ptr)` > 示例:`char*` 指针 `+1` 偏移 1 字节,`int*` 指针 `+1` 偏移 4 字节,体现了类型对运算的修饰作用[^3][^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值