数组 基础知识

数组的概念

数组是相同类型的变量的有序集合

int a[5];

数组示意图:数组包含5个int类型的数据
这里写图片描述

数组的大小

数组在一片连续的内存空间中存储元素。
数组元素的个数可以显式隐式指定。

这里写图片描述
对于a,a[2]a[3]a[4]都为0;对于b,元素个数为2。
在定义数组并初始化的时候,给数组的前几位初始化设置相应的值之后,如果没有给后几位初始化,系统将自动将后面的数组元素值初始化设置为0。
可以利用此来设置一个全0数组:int a[5] = {0};将第一个元素初始化为0,后面的自动初始化为0。
初始化比赋值更高效,因此可以尽量采用初始化。

数组地址与数组名

数组名代表数组首元素的地址
数组的地址需要用取地址符&才能得到
数组首元素的地址值与数组的地址值相同,但是意义不同。
数组首元素的地址与数组的地址是两个不同的概念

数组名的盲点:
数组名可以看做一个常量指针不能作左值,数组名“指向”的是内存中数组首元素的起始位置,在表达式中数组名只能作为右值使用。

只有在下列场合中数组名不能看做常量指针:

  • 数组名作为sizeof操作符的参数,sizeof(a)表示a整个数组的字节数。
  • 数组名作为&运算符的参数,表示整个数组的地址。

举例,下面的错误做法:
这里写图片描述
这样的做法是错误的,常量指针数组名不能作左值。编译直接报错。

例程分析:

#include <stdio.h>

// another file
// char* p = "Hello World!";

extern char p[];

int main()
{
    printf("%s\n", p);

    return 0;
}

定义为指针,声明为数组。程序输出的结果是乱码,不是“Hello World!”。在其他文件定义p指针时,编译器为p分配一个4字节的空间,存入了“Hello World!”字符串的首地址,在extern声明的时候,声明为数组,这样编译器把字符串的首地址转变为数组的各个元素的内容,存放在数组p中。这样打印出来的就是字符串的地址,而不是字符串的内容。
由上面的程序可以看出,虽然数组名可以看作一个常量指针,但是编译器对指针和数组的处理是不同的。以printf(“%s\n”, p);这句话为例,当p为指针的时候,编译器会寻址,打印出以p的内容为地址的内存中的内容。但是当p为数组的时候,只会直接打印出p数组的内容。
由此可见,编译器处理指针时,会做一次寻址,处理数组时,不会寻址。

把上面的程序改为:
printf("%s\n", (char *)(*((unsigned int *)p)));
这样打印出来的就是“Hello World!”。
首先,将p数组转变为一个指向unsigned int类型的指针,p数组有4字节unsigned int类型也是4字节,把p由指向数组首地址的指针,转变为指向整个存放字符串地址的内存的指针。然后加星号*,得到p指针指向的内存的内容,也就是字符串的地址,再把该内容转变为指向字符的指针类型,最后得到指向字符串的指针,打印出字符串的内容。
但是最好的修改方式,就是定义为指针,同样也要声明为指针。

数组小结

数组是一片连续的内存空间
数组的地址和数组首元素的地址意义不同
数组名在大多数情况下被当成常量指针处理
数组名其实并不是指针,在外部声明时不能混淆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值