为什么指针+ 1实际上加4
#include int main(void){ int *ptr,a,b; a = ptr; b = ptr + 1; printf("the vale of a,b is %x and %x respectively",a,b); int c,d; c = 0xff; d = c + 1; printf("the value of cd are %x and %x respectively",c,d); return 0; }
输出值是
the vale of a,b is 57550c90 and 57550c94 respectively the value of cd are ff and 100 respectively%
事实certificate,ptr + 1实际上是这样的?
考虑指针是什么……它是一个内存地址。 内存中的每个字节都有一个地址。 因此,如果你有一个4字节的int
并且它的地址是1000,11001实际上是那个int
的第二个字节而1002是第三个字节而1003是第四个字节。 由于int
的大小可能因编译器而异,因此当你增加指针时,你必须得到int
中某个中间点的地址。 因此,根据您的数据类型确定要跳过多少字节的工作是为您处理的,您可以使用您获得的任何值而不用担心它。
正如Basile Starynkvitch所指出的,这个数量将根据指向的数据成员的sizeof
属性而变化。 很容易忘记即使地址是顺序的,对象的指针也需要考虑容纳这些对象所需的实际内存空间。
因为指针设计为与数组兼容:
*(pointer + offset)
相当于
pointer[offset]
因此,指针aritmetic在字节方面不起作用,但在sizeof(pointer base type)
字节大小的块方面。
你真的应该花时间阅读一本好的C编程语言书(比如K&R“C编程语言” )
指针算术是一个棘手的主题。 指针添加意味着传递给下一个指向的元素。 因此地址增加了指向元素的sizeof
。
简短的回答
指针的地址将增加sizeof(T)
,其中T
是指向的类型。 因此对于int
,指针将增加sizeof(int)
。
为什么?
首先,标准要求它。 这种行为有用的原因(除了与C的兼容性之外)是因为当你有一个使用连续内存的数据结构时,比如数组或std::vector
,只需添加就可以移动到数组中的下一个项目一个指针。 如果要移动到容器中的第n个项目,只需添加n。
能够编写firstAddress + 2
比firstAddress + (sizeof(T) * 2)
简单得多,并且有助于防止开发人员假设sizeof(int)
为4(可能不是)并编写类似firstAddress + (4 * 2)
。
事实上,当你说myArray[4]
,你说的是myArray + 4
。 这就是数组索引从0开始的原因; 你只需要加0来得到第一个元素(即myArray指向数组的第一个元素),然后n得到第n个元素。
如果我想一次移动一个字节怎么办?
sizeof(char)
保证大小为一个字节,因此如果您真的想一次移动一个字节,则可以使用char*
。
指针用于指向已分配对象的内存标记的特定字节(从技术上讲,它可以指向任何位置,但这就是它的使用方式)。 当您执行指针运算时,它会根据指向的对象的大小进行操作。 在您的情况下,它是一个指向整数的指针,每个整数的大小为4个字节。
让我们考虑指针p
。 表达式p+n
类似于(unsigned char *)p + n * sizeof *p
(因为sizeof(unsigned char) == 1
)。 试试这个 :
#include #define N 3 int main(void) { int i; int *p = &i; printf("%p\n", (void *)p); printf("%p\n", (void *)(p + N)); printf("%p\n", (void *)((unsigned char *)p + N * sizeof *p)); return 0; }