前提:什么是声明什么是定义?
声明相当与普通的声明:它所说明的并非自身,而是描述其他地方创建的对象。声明可以多次出现,描述对象的类型,用于纸袋其他地方定义的对象。eg:extern int my_array[100]
定义相当与特殊的声明:它为对象分配内存,只能出现在一个地方,确定对象的类型并非内存,用于创建新的对象。eg:int my_array[100]
1:数组和指针的访问:
x=y:
x:在这个上下文环境中,x的含义是x所代表的地址,被称作左值,在编译的时候可知,是存储结构的地方。
y:在这个上下文环境中,y的含义是y锁代表的地址的内容,被称作右值,直到运行的时候才值,如无特别说明,右值代表Y的内容
(可修改的左值:是因为可以被赋值,然而,数组名也用于确定对象在内存中的位置,也是左值,但是它不能被赋值,所以它是不可修改的左值)
数组:char a[9]="abcdefg"
编译器符号标有一个符号a,它的地址:9980。
(1)取i的值,与9980相加
(2)取地址(9980+i)的内容
指针:char *p;
编译器符号表有一个符号p,它的地址是:4680
(1)取出4680中的值:‘5080’
(2)取出5080中的值
当”定义为数组,用数组的方式引用“:
char *p="abcdefg";
编译器符号标中有意个符号P,它的地址是:4680
(1)取出4680的值:‘5080’
(2)取出i的值,与5080相加
(3)取出5080+i的值
ps:在使用声明和定义的时候,声明和定义必须一致。
2:指针与数组的区别
(1)指针保存的是保存数据的地址,数组直接保存数据
(2)指针是间接访问,首先取出指针的内容,然后将它作为地址再取出内容,而数组是直接访问。
(3)指针通常用于动态数据结构,数组通常用于存储固定数目的元素
(4)指针通过malloc分配内存,free释放内存,数组是隐式分配和删除
(5)指针通常指向匿名数据,数组即为数据名
定义指针的时候,编译器并不为指针所指向的内容分配空间,它只分配指针本身的空间,除非在定义同时赋予指针一个字符串。而数组在定义的时候就已经指明了数组的大小。而只有字符串常量可以给指针分配空间,例如:float *p=3.14则不能分配。而数组也可以通过定义来初始化,char a[]="abcdefg",而且可以通过strncpy(a,hijk,4)将数组变为:a[]="hijkefg"。指针就不行。
3:指针和数组什么时候是相同的:
所有作为函数参数的数组名总是可以通过编译器转换为指针。
不能写成指针方式的
(1)extern,eg extern char a[],不能修改为指针的形式
(2)定义:char a[10]:不能修改为指针形式
能写成指针方式的:
函数的参数:eg func(char a[])就可以写成func(char *a)
c=a[i]:也可以写为指针的形式
对于编译器来说:一个数组就是一个地址,而一个指针是一个地址的地址
数组名通常被当作指向第一个元素的指针。
4:关于数组和指针的规则
规则一:
“表达式中的数组名”就是指针
数组的下表引用总是可以写成“一个指向数组的起始地址的指针加上偏移量”
eg:int a[10],*p,i=2;访问a[i]的方法有:
(1)p=a;p[i]; (2)p=a;*(p+i) (3)p=a+i;*p;
在表达式中指针和数组可以互换是因为在编译器中,他们的最终形式都是指针。
规则二:
C语言把数组下表作为指针的偏移量
规则三:
“作为函数参数的数组名”等同与指针
5:关于多维数组
对于某些结构比如说动态数组,程序员必须使用指针显示的分配和操纵内存,而不是由编译器完成
数组的分配是“行式”的
(1)指针数组就是Iliffe向量
可以通过声明一个一维指针数组,其中每个指针指向一个字符串来取得类似二维字符数组的效果
二维数组是“数组的数组”
eg char a[4][6]
在编译器的符号表中有个a的地址是9980
1)取出i的值,把它的长度调整为一个行的宽度,(这里是6),然后加到9980上
2)取出j的值,把它的长度调整成一个元素的宽度,(这里是1),然后加到前面的结果上
3)从(9980+6*i+j*1)中取出结果
eg:char *p[4]
字符串指针数组中的p的地址是4624
1)取出i的值,乘指针的宽度4*i
2)从(4626+4*i)中取出内容“5081”
3)取出j的值,乘元素的宽‘1’,并把结果加到5081上
4)从地址(5081+j*1)取出内容
阅读(1217) | 评论(0) | 转发(0) |