为什么指针可以赋值?

时间:2014-01-31 21:12:10

标签: c pointers

我有一个难题:

int *a=*b;
a[1]=3;
a[2]=5

a是指针数组,并将值指定为b。根据我的理解,[]应该是一个地址,那么为什么在实践中我们可以为指针(在本例中为[])的位置赋值?有没有解释?

2 个答案:

答案 0 :(得分:2)

我假设这是C或Objective C / C ++的C子集,因为C +,Java,PHP和其他类C语言不使用指针。

每行使用代码标记和单个语句。

声明

int *a = *b;

创建一个指向int的指针。不是指向int的指针,指向int的指针。

然后将a中的当前地址设置为b的解引用,无论b是什么。你没有显示b的声明。除非b的类型为int **,否则您应该收到编译器警告。

a不是指针数组。 a是指向int的指针。它可以指向单个int,也可以指向一个int数组。编译器无法区分......

如果b的类型为int **,或者是指向int的指针,那么你的语句会取消引用其中一个指针并指向b中的第一个子数组。

代码

a[1] = 3;

假设a是一个指向整数数组的指针,并且由于编译器不能进行任何范围检查,它会尝试索引到数组并将值保存到内存块中的第二个int,即一个点至。如果a没有指向足够大的内存块以包含至少2个整数,则此语句可能会在使用受保护内存的现代计算机上崩溃,它也可能只是覆盖后面的内存。

作为@EdS。在下面的评论中指出,这在业务中称为

“未定义的行为”

如果您要使用这样的C指针,那么您需要确保它确实指向有效内存,如果您要使用指针就好像它是一个数组,那么你需要确保不要超过指针所指向的内存范围。

答案 1 :(得分:1)

但是,让我们回答你的问题:

我将逐步完成您的代码(虽然我为了示例的目的对其进行了一些修改),并向您展示它在假存储器中的作用,因此您明白了这一点:

int b[4];

这里你分配4个内存单元,并为包含第一个内存单元地址的内存单元制作b标签:

variable     b                      
address      0x1   0x2 0x3 0x4 0x5 
memory      [0x2] [   |   |   |   ]

然后:

int* a = b;

这里你分配一个可以包含地址的新内存单元,因为它是用指针​​类型声明的,你为它分配了b内存单元格的内容:

variable     b                       a
address      0x1   0x2 0x3 0x4 0x5   0x6
memory      [0x2] [   |   |   |   ] [0x2]

然后:

a[1]=3;
a[2]=5;

您将值设置为a[1],使用指针算法转换为*(a+1),这是地址0x2 + 1的内容,即0x3的内容。与a[2]相同。记忆现在是:

variable     b                       a
address      0x1   0x2 0x3 0x4 0x5   0x6
memory      [0x2] [   |  3|  5|   ] [0x2]

我希望这个ASCII能让阵列​​更加清晰!你一定要阅读Kernighan and Ritchie book,以及this documentation,它们都能很好地解释整个内存的管理方式,以及指针算术和数组。