C语言指针学习(二) ---- 指针与数组

来源:互联网 发布:知乎的童瑶事件 编辑:程序博客网 时间:2024/05/16 09:21

仅供自己学习用!


当定义一个数组的时,数组的名称保存了数组第一个元素的地址 ,实际上数组名可以直接理解为指针:


int a[5] // a表示的是数组的名称,而5表示a数组一共有5个元素

# include <stdio.h>int main(void){int a[5];int b[5];a=b //error, a是常量printf("%#X", &a[0]);printf("%#X", a);return 0;}


尽管数组的个数一样,但不可以将b赋值给a,因为数组名是指针常量,是指向内存空间的一个常量,本身不能做左值被修改,因此c语言中不可以将数组直接相等,如果不想用for循环一个一个的赋值就需要 内存拷贝函数函数 :memcpy

%#X 表示用16进制输出,这两行输出的结果是相同的,都是a数组的第一个元素的地址


1.指针和数组的关系:

当一个指针变量被初始化一个数组名,说明该指针变量就指向该数组,例如:

char str[20], *ptr;ptr=str;

指针ptr被指向数组str的第一个元素的地址,因为数组名就是该数组的首地址,也是数组的第一个元素的地址,此时可以认为指针ptr就是数组str(反之不成立!!),这样原来对数组的处理可以用指针来实现,如对数组元素的访问,既可以用下标变量访问,也可以用指针访问。

2.指向数组元素的指针:

如有定义

int a[10], *p;p=a;

实际上 p=&a[0], 是将a数组的第一个元素的地址赋值给了指针变量p

实际上在C语言中数组名就是数组的首地址,因此数组的首地址可以通过两种方式获得:p=&a[0] 或者 p=a

这两种方式在形式上相似,区别在于p是指针,而a是数组名。p是一个可以变量,一个可以变化的指针变量,而a是一个常数,数组一经被申明,其地址就不可以改变,因此a是不可变的。于是a++或者++a都是错误的,而p++或者++p却是正确的. 由此可见,数组和指针的紧密联系。

3.指针与一维数组:

要理解指针和一维数组的关系,就必须知道在编译系统中,数组的存储组织形式和对数组元素的访问方法。

一维数组是一个线性表,它被存放在一片连续的内存单元中。c语言对数组的访问是通过数组名(数组的起始地址)加上相对于起始地址的相对量(由下表控制),得到要访问的数组元素的单元地址,然后再对计算出的单元地址的内容进行访问。通常把数据类型所占单元的字节个数称为扩大因子。

实际上编译系统将数组元素的形式a[i] 转换成 *(a+i), 然后才进行运算。对于一般数组元素的形式:<数组名>[<下标表达式>],编译程序将其转换成:*(<数组名>+<下标表达式>),其中下标表达式为:下标表达式*扩大因子。整个式子计算结果是一个内存地址,最后的结果为:*<地址>=<地址所对应单元的地址的内容>。由此可见,C语言对数组的处理,实际上是转换成指针地址的运算。

数组与指针暗中结合在一起。因此,任何能由下标完成的操作,都可以用指针来实现,一个不带下标的数组名就是一个指向该数组的指针。


4.指针与字符数组
C语言中许多字符串操作都是由指向字符数组的指针及指针的运算来实现的。因为对于字符串来说,一般都是严格的顺序存取方式,使用指针可以打破这种存取方式,更为灵活地处理字符串。

另外由于字符串以′\0′作为结束符,而′\0′的ASCII码是0,它正好是C语言的逻辑假值,所以可以直接用它作为判断字符串结束的条件,而不需要用字符串的长度来判断。C语言中类似的字符串处理函数都是用指针来完成,使程序运行速度更快、效率更高,而且更易于理解。


示例:

# include <stdio.h>void updateArr(int * pArr){pArr[1] = 22;}int main(void){int a[3] = {1, 2, 3};printf("%d\n", a[1]);   //output is 2updateArr(a);printf("%d\n", a[1]);   //output is 22return 0;}

注释:

1. 之所以main函数可以传递数组名给updateArr函数,是因为数组名a实际上就是一个指向该数组首地址的指针

2.调用函数updateArr函数后,原数组a的第二个元素的值更改的原因是:传递给函数的变量是一个指针变量(数组名a),该指针变量存放了a数组首地址的值,因此pArr实际上和a 在内存中指向同一个地址单元----换句话说,a和pArr实际上就是相同的,可以互相替换!

pArr[i]  =  *(pArr+1) = a[i] = *(a+1) 这4个实际上都是一个意思,一个表达式

3.由于pArr[i] 等同于 a[i], 那么在函数对pArry[i] 的任何操作(如更改值),都等同于在main函数中对数组a[i] 的操作!





原创粉丝点击