C指针和数组区别

377 阅读3分钟

文章目的:主要帮助刚接触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语言各种语法操作就非常明了。回到原点,数组和指针其实都是语法糖。关键还是在于对内存操作的理解。