引入
我们的前提是下面几个变量:
int array[10];
int *p;
int var;
下面六种赋值之后,变量var
的值是否相同?
var = array[4]
var = *(array + 4)
var = 4[array]
p = &[array4]; var = *p;
var = *(int *) ( (void *)array + 4 * (sizeof(int)))
p = &var; *p = *(array + 4);
当然看到这里,如果你已经有非常自信的答案,你当然可以无视这一篇文章后面的部分。
答案
上面六种赋值之后,变量var
的值相同。
我们来分析一下这个数组在程序的栈的布局 (这里Address 10568
仅为array
地址的例子):
+---------------------+-------------+---------+
| Variable Name | Address | Value |
+---------------------+-------------+---------+
| array | 10568 | 0 |
| | +---------+
| | | 1 |
| | +---------+
| | | 2 |
| | +---------+
| | | 3 |
| | +---------+
| | | 4 |
| | +---------+
| | | 5 |
| | +---------+
| | | 6 |
| | +---------+
| | | 7 |
| | +---------+
| | | 8 |
| | +---------+
| | | 9 |
+---------------------+-------------+---------+
var = array[4]
, var = *(array + 4)
, var = 4[array]
, p = &[array4]; var = *p;
:
这四种其实非常类似,都是已知array
是一个int*
,在array
这个基地址(例子中的10568)上进行四个元素的偏移,因此能落在4号元素的地址上,再讲这个地址视作int*
读出int内容。
var = *(int *) ( (void *)array + 4 * (sizeof(int)))
:
这个写法虽然繁琐,但是非常像对应的汇编代码。(void *)array
首先将array
转成一个void*
,也就是抹去了它int*
的原身份。再对这个void*
空类型指针进行偏移操作,注意这时候的偏移量不再是4,而是对应4个int
对应的Byte量,即4 * (sizeof(int)
。最后再将这个空类型指针转化成int*
去读取数据。
p = &var; *p = *(array + 4);
:
利用了另外一个指针p
,使这个指针指向变量var
。因此可以使用*p
对var
进行赋值。
另一例子
我们可以练习,考虑一下这个程序的输出。
int array[10];
int *p;
int var;
for(int i = 0; i < 10; i++) array[i]=i;
var = array[4];
printf("%i\n", var);
var = 5[array];
printf("%i\n", var);
var = *(array + 6);
printf("%i\n", var);
p = &array[7];
var = *p;
printf("%i\n", var);
p = array;
var = *p;
printf("%i\n", var);
p = &var;
*p = *(array + 3);
printf("%i\n", var);
输出:
4
5
6
7
0
3
对应的代码:
点击下载
引用和推荐的阅读:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。