2016-10-22 138 views
0

我对手动指定了带偏移量的指针的整数值,看起来ptr+1实际上并不指向second_int,或者是因为printf函数不知道大小的ptr+1将偏移值赋值给指针C

#include <stdio.h> 

int main(void) 
{ 
    int first_int = 42; 
    int second_int = 23; 

    int *ptr = &first_int; 
    *(ptr + 1) = second_int; 

    int i = 0; 
    for (i = 0; i < 2; i++) { 
     printf("%d\n", *(ptr+i)); 
    } 

    return 0; 
} 

,输出是:

42 
1

难道不应该是42和23?

而且我发现每次我打印*(ptr+1)时,它递增1

#include <stdio.h> 

int main(void) 
{ 
    int first_int = 42; 
    int second_int = 23; 

    int *ptr = &first_int; 
    *(ptr + 1) = second_int; 

    int i = 0; 
    for (i = 0; i < 10; i++) { 
     printf("%d\n", *(ptr+1)); 
    } 

    return 0; 
} 

,输出是:

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

发生了什么?

编辑:
我只允许使用指针,但并非阵列(做学习C坚硬方式锻炼; Tibial)。所以我通过int *ptr = malloc(sizeof(int) * 2);手动为ptr分配内存,然后我给ptrptr + 1赋值,并且代码按预期运行。

+3

未定义的行为发生。 second_int不保证与first_int相关的特定位置,更不用说您期望的。你已经践踏了记忆中的其他地方,我猜想它属于变量“i”。 –

+1

你为什么认为ptr + 1指向second_int? – immibis

回答

0

在您的代码中,ptr+1不是由您管理的内存。
它可以被其他程序或任何零件或程序使用。这里发生的事情是编译器优化了second_int,因为只使用它的值。所以没有内存分配给它。
幸运的是,内存中的下一个int也由您管理,并且它是您的循环的索引。
你以为内存布局是这样的:
first_int | second_int | i

但它是像这样:
first_int | i

如果你希望能够指既诠释了指针+偏移,那么你必须声明为一个数组,以确保它们是连续存储:
int my_ints[2] = { 42, 0};
int *ptr = my_ints;
*(ptr+1) = second_int;
然后你的代码将按预期工作。

+0

非常感谢,学到了很多! – xawyzen

2

当您有一个指向单个值的指针时,您只能取消引用它以访问该特定值,而不是其他值。为了能够增加一个指针,它必须指向数组内的一个对象。

E.g.这将是有效的:

int integers[2]; 
int *ptr = &integers[0]; 

*(ptr + 1) = 2; // Sets integers[1]. 

你似乎想设置*(ptr + 1)second_int点。在C语言中,唯一可以指向单个值变量的方法是使用地址运算符,即&second_int。但是该值的类型是int*,而不是int。我想,也许你想是这样的:

int first_int = 42; 
int second_int = 23; 

int *array[2]; 
array[0] = &first_int; 
array[1] = &second_int; 
int **ptr = &array[0]; 

现在你可以使用**ptr*ptr[0]访问first_int**(ptr + 1)*ptr[1]访问second_int

+0

你确定你的意思是“递减”而不是“解除引用”吗? – EOF

+0

@EOF啊,谢谢。 –

+0

另外,你*被允许增加一个指向单个对象的指针。指针可能指向*数组或对象,您无法取消引用这样的指针。 – EOF