<span style="font-size:18px;">最近被数组,指针搞晕了,查了一些资料,也看了《C专家编程》这本书,对这些有了些了解。
下面写的这些东西时我个人的理解,如有不正确的地方,还望各位大神指正!
<span style="font-size:24px;"><strong>数组与指针的异同点</strong></span>
<strong>1、数组与指针的的不同点</strong>
很多时候数组和指针是一样的,但在C语言中两者确实有区别。
数组名就代表的该数组的第一个元素的地址,而指针存储的值才代表地址。
以下是节选自《C专家编程》中的一段话:</span>
char a[9]="abcdefgh"; c=a[i];
编译器符号表具有一个地址9980
运行时步骤1:取i的值,将它与9980相加
运行时步骤2:取地址(9980+i)的内容
char *p; ......... c=*p;
编译器符号表游弋ge符号p,他的地址为4624
运行时步骤1:取地址4624的内容,就是‘5081’
运行时步骤2:取地址5081的内容
char *p="abcdefgh"; c=p[i];
编译器符号表有一个p,地址为4624
运行时步骤1:取地址4624的内容,即‘5081’
运行时步骤2:取得i的值,并将它与5081相加
运行时步骤3:取地址[5081+i]的内容
C语言中“地址X”和“地址X的内容”都是用一个符号来表示的,为左值时,就代表“地址X”,为右值时就代表“地址X的内容”。
每个符号的地址在编译时可知,所以编译器需要一个地址来执行某种操作时,它就可以直接进行操作,并不需要增加指令首先取得具体的地址。相反,对于指针,必须首先在运行时取得它的当前值,然后才能对它进行解引用操作
相比于数组,指针操作多了依次额外的提取。
也就是说数组和指针在c语言中实际上是有区别的,尽管它们很多时候是相同的。所以定义数组后,再声明时也必须声明为数组类型,指针也一样。定义为对象分配内存,声明只是描述其他地方创建的对象。extern对象声明告诉编译器对象的类型和名字,对象的内存分配则在别处进行。由于并未在声明中为数组分配内存,所以并不需要提供关于数组长度的信息。
两者的具体区别为:
指针 | 数组 |
---|---|
保存数据的地址 | 保存数据 |
简介访问数据,首先取得指针的内容,把它作为地址,然后从这个地址取得数据。如果指针有一个下标【i】,就把指针的内容加上i作为地址,从中提取数据 | 直接访问数据,a[i]只是简单地以a+i为地址取得数据 |
通常语用动态数据结构 | 通常用于存储固定数目且数据类型相同的元素 |
相关的函数为malloc(),free() | 隐式分配和删除 |
通常指向匿名数据 | |
2、数组和指针相同的时候
3、字符数组与字符指针
4、一段测试的代码
#include<iostream>
#include<stdio.h>
using namespace std;
void fun1(char ca[]) //数组作为形参,进入函数内部还是当做字符指针处理
{
cout<<"利用cout:"<<endl;
cout<<"ca="<<ca<<" "<<"&ca="<<&ca<<endl;
cout<<"ca[0]="<<ca[0]<<" "<<"&(ca[0])="<<&(ca[0])<<endl;
cout<<"ca[1]="<<ca[1]<<" "<<"&(ca[1])="<<&(ca[1])<<endl<<endl;
cout<<"利用printf:"<<endl;
printf(" addr of array param = %#x \n",&ca); //此处ca还是相当于字符指针,此处输出的是字符指针本身的地址,而不是其所指向的地址。
printf(" addr (ca[0]) = %#x \n",&(ca[0])); //此处输出的是指针所指向的地址,也可以直接用ca输出,即实参数组的地址。
printf(" addr (ca[1]) = %#x \n",&(ca[1]));
printf(" ++ca = %#x \n\n\n",++ca);
}
void fun2(char *pa) //指针作为形参
{
cout<<"利用cout:"<<endl;
cout<<"pa="<<pa<<" "<<"&pa="<<&pa<<endl;
cout<<"pa[0]="<<pa[0]<<" "<<"&(pa[0])="<<&(pa[0])<<endl;
cout<<"pa[1]="<<pa[1]<<" "<<"&(pa[1])="<<&(pa[1])<<endl<<endl;
cout<<"利用printf:"<<endl;
printf(" addr of ptr param = %#x \n",&pa);
printf(" addr (pa[0]) = %#x \n",&(pa[0]));
printf(" addr (pa[1]) = %#x \n",&(pa[1]));
printf(" ++pa = %#x \n\n\n",++pa);
}
char ga[10] = "hddufhugf";
int main(int argc,char *argv[])
{
cout<<"main()函数中:"<<endl<<endl;
cout<<"利用cout:"<<endl;
cout<<"ga="<<ga<<" "<<"&ga="<<&ga<<endl;
cout<<"ga[0]="<<ga[0]<<" "<<"&(ga[0])="<<&(ga[0])<<endl;
cout<<"ga[1]="<<ga[1]<<" "<<"&(ga[1])="<<&(ga[1])<<endl<<endl;
cout<<"利用printf:"<<endl;
printf(" addr of global array = %#x \n",&ga); //此处用直接用ga输出数组的地址也可以,用%x
printf(" addr (ga[0]) = %#x \n",&(ga[0]));
printf(" addr (ga[1]) = %#x \n\n\n",&(ga[1]));
cout<<"fun1(char ca[])函数中:"<<endl<<endl;;
fun1(ga);
cout<<"fun2(char *pa)函数中:"<<endl<<endl;
fun2(ga);
return 0;
}
该段代码用g++编译后运行结果如下:
main()函数中:
利用cout:
ga=hddufhugf &ga=0x804b040
ga[0]=h &(ga[0])=hddufhugf
ga[1]=d &(ga[1])=ddufhugf
利用printf:
addr of global array = 0x804b040
addr (ga[0]) = 0x804b040
addr (ga[1]) = 0x804b041
fun1(char ca[])函数中:
利用cout:
ca=hddufhugf &ca=0xbfd543a0
ca[0]=h &(ca[0])=hddufhugf
ca[1]=d &(ca[1])=ddufhugf
利用printf:
addr of array param = 0xbfd543a0
addr (ca[0]) = 0x804b040
addr (ca[1]) = 0x804b041
++ca = 0x804b041
fun2(char *pa)函数中:
利用cout:
pa=hddufhugf &pa=0xbfd543a0
pa[0]=h &(pa[0])=hddufhugf
pa[1]=d &(pa[1])=ddufhugf
利用printf:
addr of ptr param = 0xbfd543a0
addr (pa[0]) = 0x804b040
addr (pa[1]) = 0x804b041
++pa = 0x804b041