2011-04-10 174 views
38

指针的值是变量的地址。为什么int pointer的值在int指针增加1后增加了4个字节。为什么int指针'++'增加4而不是1?

在我看来,我认为指针增量后指针(地址变量)的值只增加1个字节。

测试代码:

int a = 1, *ptr; 
ptr = &a; 
printf("0x%X\n", ptr); 
ptr++; 
printf("0x%X\n", ptr); 

预期输出:

0xBF8D63B8 
0xBF8D63B9 

实际输出:

0xBF8D63B8 
0xBF8D63BC 

编辑

的其他问题 - 如何访问4个字节一个int占用一个接一个?

回答

92

当您增加T*时,它将移动sizeof(T)字节。 这是因为移动任何其他值没有意义:例如,如果我指向的大小为4个字节的int,例如,小于4的增量会使我处于什么状态?部分int与其他一些数据混合:无意义。


在内存试想一下:

[↓  ] 
[...|0 1 2 3|0 1 2 3|...] 
[...|int |int |...] 

当我增加该指针哪个更有意义?这:

  [↓  ] 
[...|0 1 2 3|0 1 2 3|...] 
[...|int |int |...] 

或者这样:

 [↓  ] 
[...|0 1 2 3|0 1 2 3|...] 
[...|int |int |...] 

最后并没有实际指向的任何形式的int。 (从技术上讲,然后,使用指针UB

如果你真的要移动一个字节,递增char*:的char大小始终是一个:

int i = 0; 
int* p = &i; 

char* c = (char*)p; 
char x = c[1]; // one byte into an int 

†这个推论是,您不能增加void*,因为void是不完整的类型。

+0

“你不能增加'void *',因为'void'是一个不完整的类型” - true,但是gcc支持'void *'上的算术作为扩展(它把它看作是'char *')。 – 2016-01-13 18:57:07

+0

“它对于一个整数几乎总是没有意义”,但对于像可变长度结构数组这样的情况来说它是非常有意义的(“我有一个缓冲区充满了数据包,我想将CurrentPacketPointer移动到下一个包”)。 – 2016-08-15 03:05:54

+0

“如果你真的想移动一个字节,增加一个char *:char的大小总是为1”不,它不总是一个,你应该使用'uint8_t'来代替。 – Winter 2017-07-17 16:11:07

8

指针增量基于指向的类型的大小。如果int是4个字节,递增1的int *如果一个短为2个字节由4.

将增加它的价值,增加短* 1将由2.

这是增加其值C指针算术的标准行为。

+0

我想他是在寻求理由。 – GManNickG 2011-04-10 07:20:40

+0

希望很明显,基本原理是指针算术总是以指针对象的大小为单位进行工作。 – 2011-04-10 07:23:20

+0

理由是*为什么*就是这种情况。 – GManNickG 2011-04-10 07:25:06

1

这个想法是,增加后,指针指向内存中的下一个int。由于整数是4个字节宽,所以它增加了4个字节。通常,指向类型T的指针将按sizeof(T)递增

1

如您所说,int pointer指向int。一个int通常占用4个字节,因此,当你增加指针时,它指向存储器中的“下一个”int - 即增加4个字节。它适用于任何类型的任何尺寸。如果你有一个指向A的指针,然后增加一个A*它将增加sizeof(A)

想一想 - 如果你只增加一个字节的指针,它会指向一个int的中间,我不能想到这是一个需要的机会。例如,当迭代数组时,这种行为非常舒服。

2

指针是增加了它们指向的类型的大小,如果指针指向炭,pointer++将递增1指针,如果它指向一个1234个字节结构,pointer++将由1234

递增指针

这可能会让你第一次遇到它就感到困惑,但实际上它有很大的意义,这不是一个特殊的处理器特性,但编译器会在编译过程中计算它,所以当你编写pointer+1时,编译器将它编译为pointer + sizeof(*pointer)