C语言-数组和指针之间的较量

1 使用背景
    当人们在学习编程时,可以看到大量的数组与指针互换的使用实例,比如下面的这个例子:
    char my_array[10];
    char *my_ptr;
    ...
    i = strlen(my_array);
    i = strlen(my_ptr);
    还有很多类似的语句:printf("%s %s", my_ptr, my_array);这些都展示了数组与指针的可混换性,所以人们很容易认为数组和指针基本上是一样的。
    数组和指针是相同的吗?答案是否定的,相信你也不会同意他们是一回事的说法。最常见的错误使用指针与数组的环境是这样的:
    文件1:
    int var[100];

    文件2:
    extern int *var;

    文件1定义了数组var,文件2声明了它为指针,对于那些认为C语言中数组和指针非常相似的观点根深蒂固的程序员来说,会觉得这样没什么不妥,但是当你在文件2中使用var的时候会发现者根本行不通。话说两个不同类型能直接互换吗,这和下面使用有什么分别?
    文件1:
    int var;

    文件2:
    extern float var; 
    指针就是指针,数组就是数组,他们只是在特定的场合下才用相同的功用,就因为这些功用的场合出现的极为频繁才导致两者混淆的思维。

2 声明与定义
    定义:只能出现在一个地方,确定对象类型并分配内存,用于常见新的对象(int var[100])。
    声明:可以出现多次,描述对象的类型,用于指代其他地方定义的对象,比如其他文件中声明的对象(extern int var[])。

    从上面的他们的定义可以看出,如果要区分定义和声明很简单,只要记住:声明是普通声明,说明的不是自身而是描述其他地方创建的对象,也不需要提供长度(多维数组需要提供除最左面维度的其他维度长度);定义是特殊的声明,它为对象分配内存。

3 数组与指针的区别
   1)可修改的左值
     在C语言中,数组作为一个不可修改的左值,不能单独出现在赋值或复合赋值符的左边,但指针是可以修改的左值,可以出现在赋值或复合赋值符的左边。
    
  2)extern char a[]与extern char a[100]是等价的原因是因为:他们都标识a是一个数组,也就是一个内存地址,数组内的成员可以从这个地址找到,编译器也不需要知道数组的具体长度,因为通过偏离起始的便宜地址就可以办到,而对于extern char *a来说,它会告诉编译器p是一个指针,为了取得这个字符,必须先找到地址p的内容,把他作为字符的地址来取得这个字符,指针的访问要领了的多,但是需要增加一次额外的提取。
     其实,这说明一个事实:数组名表示数组的地址,引用变量值时只需要取一次;而指针表示存储变量值地址的地址,要得到变量的值需要取两次。如果像extern char a[]与extern char *a定义和声明变量,在extern char *a的文件中使用a[i]将会被取值两次,最后一次是将char数组中第i个元素的字符当做地址来取值,显然这是错误的。
  3)指针保存数据的地址,而数组保存的是数据,这一点从2)即可知道,简单的说:数组就是一个地址,指针就是一个地址的地址
  4)指针通常用于动态数据结构,相关函数为malloc()和free();数组通常用于存储固定数目且数据类型相同的元素,隐式分配和删除
  5)数组和指针都可以在他们的定义中用字符串常量进行初始化,看上去一样但底层的机制却不相同。对于指针:是保存了字符串常量的地址;对于数组:是将字符串常量拷贝到了申请的内存中。

4 数组与指针的共同点
  1)所有座位函数参数的数组总是可以通过编译器转换为指针,这一点可以在The C Programming Language第二版的99页底部找到:
    char s[];
  and(和)
    char *s;
  are equivalent(是一样的)...
    可以更确切的表示为:在函数参数的声明中,数组名被编译器当做指向该数组第一个元素的指针

  2)数组下表表达式总是可以改写为带偏移量的指针表达式,这里指的是表达式中,这与声明可不同哦

  3)下标总是和指针的偏移量相同,就是说用a[i]这样形式访问数组总被改写成*(a+i)这样的指针形式

5 函数数组形参为何当指针
    要回答这个问题可能需要更多的来了解编译器,全面的语义检查被可移植的C编译器所排斥,其理由是把lint这样的程序作为单独的程序,对编译器的效率会更高一些,其实,事实上现在很多现代的ANSI C编译器在错误检查方面都做了增强,这也说明了把lint程序自成一家的做法还是有相当的非议的。
    没错,吧作为形参的数组和指针等同起来是出于效率原因的考虑,在C语言中,所有的非数组形式的数据实参以传值形式调用,其实就是做了一次拷贝给函数调用,拷贝数组的代价无论在时间还是空间上的开销都可能是非常大的,其实就是这么简单。

6 总结
    学习C语言的同学都知道,数组与指针在C中的地位之高,他们俩的暧昧关系一直为人们津津乐道,或者说痛心疾首(如果你被他们折磨过),区分他们是学习C语言的重点内容,虽然接触C已经有三年了,每次学习都还是挺有收获的,再接再厉...
   
 


    

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值