文章目的:主要帮助刚接触C语言不久的小伙伴理解数组和指针区别。(这里不涉及 数组指针,指针数组的问题)新手之所以对指针和数组混淆。是因为它们语法定义上不同,部分书写语法相同。本质它们底层操作思维一样。基于这些情况,加上编译器在隐藏做了很多操作细节。导致了初学者混淆数组和指针。
数组的声明
int array[3]
非常好理解, 定义了一个数组 array
指针声明
int *point
第一种情况 假设在某个作用域的情况如下:
{
int array[3] = {1, 2, 3};
int *point ;
int number1 = array[0];
int number2 = *array++; //无法通过编译
int number3 = *point;
}
在上面例子里面 array 无法当成指针使用,即 *array++ 编译器报错。单纯的从语义上。数组跟指针完全是2个不同的东西。
第二种情况 假设在某个作用域的情况如下:
{
array[0] = 1;
}
单纯从这里无法 array是指针还是数组。因为指针和数组都支持[]语法操作。
第三种情况
{
int array[3] = {1, 2, 3};
int *point ;
point = array;
int number1 = array[0];
int number2 = point[0];
int number3 = *point;
// number1 number2 number3 完全相等
}
这里很明显可以看到 point 完全可以当成数组来用(语法上完全可以模仿指针)。但是 数组array在语法上却无法当成指针使用。数组如果写成*array++编译器通不过! 但是指针跟数组的操作思维一样的!
第四部分 int number1 = array[0] 与 int number3 = *point 区别
{
//寄存器 ax,
mov ax, 10 // 类似 C语言 int number = 10;
mov ax, [0] // 类似 C语言 int number = *point; point的地址是0
mov [0], 10 // 类似 C语言 int *point = 10; point的地址是0
mov ax, bx // 类似 int number1(类似 ax), number2(类似 ax); number1 = number2;
可以看到 汇编来看 ax 这个变量赋值就3种模式,
ax, 10 常量赋值
ax, [0] 读取0内存地址里面的值,赋值给ax
ax, bx bx的值赋值给ax
} {
int number = array[0]; 类似 mov ax [0x0001]
int number = *p; 类似 mov ax [0x0001]
int number = array[1]; 类似 mov ax [0x0004]
int number = *p++; 类似 mov ax [0x0004]
}
可以看到 从汇编的角度去看, array[0]和*p。都表示为,读取地址0x0001中的内容。然后赋值number。
总结
在线性操作上 array[]与*p 操作思维上一致。因为C语言语法糖的关系,使得数组写法上只能局限在[]。从汇编的成面上看,C语言的各种指针操作,特别是赋值操作 无非几种类型:
{
mov ax, bx; 寄存器对寄存器赋值, 类似C语言 int a, int b; a = b;
mov ax, 10; 寄存器 常量赋值 类似C语言 c = 10
mov ax, [地址]; 寄存器从读取内存某地址的内容, 类似 int a = *p;
mov [地址], 1 ; 某地址内容赋值, 类似 *p = 1;
-----------------------------------------------------------------
int a = 1; 假设a的地址为 0x0001
int *p = &a; 假设p的地址为 0x0010
这两句代码可以拆解成
mov [0x0001], 1;
mov [0x0010], 0x0001;
}
从汇编的成面看C语言各种语法操作就非常明了。回到原点,数组和指针其实都是语法糖。关键还是在于对内存操作的理解。