C 数组
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。
数组的声明并不是声明一个个单独的变量,比如 runoob0、runoob1、...、runoob99,而是声明一个数组变量,比如 runoob,然后使用 runoob[0]、runoob[1]、...、runoob[99] 来代表一个个单独的变量。
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
数组中的特定元素可以通过索引访问,第一个索引值为 0。
C 语言还允许我们使用指针来处理数组,这使得对数组的操作更加灵活和高效。
声明数组
在 C 中要声明一个数组,需要指定元素的类型和元素的数量,如下所示:
type arrayName [ arraySize ];
这叫做一维数组。arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C 数据类型。例如,要声明一个类型为 double 的包含 10 个元素的数组 balance,声明语句如下:
double balance[10];
现在 balance 是一个可用的数组,可以容纳 10 个类型为 double 的数字。
初始化数组
在 C 中,您可以逐个初始化数组,也可以使用一个初始化语句,如下所示:
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目。
如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,如果:
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
您将创建一个数组,它与前一个实例中所创建的数组是完全相同的。下面是一个为数组中某个元素赋值的实例:
balance[4] = 50.0;
上述的语句把数组中第五个元素的值赋为 50.0。所有的数组都是以 0 作为它们第一个元素的索引,也被称为基索引,数组的最后一个索引是数组的总大小减去 1。以下是上面所讨论的数组的的图形表示:
下图是一个长度为 10 的数组,第一个元素的索引值为 0,第九个元素 runoob 的索引值为 8:
访问数组元素
数组元素可以通过数组名称加索引进行访问。元素的索引是放在方括号内,跟在数组名称的后边。例如:
double salary = balance[9];
上面的语句将把数组中第 10 个元素的值赋给 salary 变量。下面的实例使用了上述的三个概念,即,声明数组、数组赋值、访问数组:
实例
当上面的代码被编译和执行时,它会产生下列结果:
Element[0] = 100 Element[1] = 101 Element[2] = 102 Element[3] = 103 Element[4] = 104 Element[5] = 105 Element[6] = 106 Element[7] = 107 Element[8] = 108 Element[9] = 109
获取数组长度
数组长度可以使用 sizeof 运算符来获取数组的长度,例如:
int numbers[] = {1, 2, 3, 4, 5}; int length = sizeof(numbers) / sizeof(numbers[0]);
实例
int main() {
int array[] = {1, 2, 3, 4, 5};
int length = sizeof(array) / sizeof(array[0]);
printf("数组长度为: %d\n", length);
return 0;
}
使用宏定义:
实例
#define LENGTH(array) (sizeof(array) / sizeof(array[0]))
int main() {
int array[] = {1, 2, 3, 4, 5};
int length = LENGTH(array);
printf("数组长度为: %d\n", length);
return 0;
}
以上实例输出结果为:
数组长度为: 5
数组名
在 C 语言中,数组名表示数组的地址,即数组首元素的地址。当我们在声明和定义一个数组时,该数组名就代表着该数组的地址。
例如,在以下代码中:
int myArray[5] = {10, 20, 30, 40, 50};
在这里,myArray 是数组名,它表示整数类型的数组,包含 5 个元素。myArray 也代表着数组的地址,即第一个元素的地址。
数组名本身是一个常量指针,意味着它的值是不能被改变的,一旦确定,就不能再指向其他地方。
我们可以使用&运算符来获取数组的地址,如下所示:
int myArray[5] = {10, 20, 30, 40, 50}; int *ptr = &myArray[0]; // 或者直接写作 int *ptr = myArray;
在上面的例子中,ptr 指针变量被初始化为 myArray 的地址,即数组的第一个元素的地址。
需要注意的是,虽然数组名表示数组的地址,但在大多数情况下,数组名会自动转换为指向数组首元素的指针。这意味着我们可以直接将数组名用于指针运算,例如在函数传递参数或遍历数组时:
实例
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 数组名arr被当作指针使用
}
}
int main() {
int myArray[5] = {10, 20, 30, 40, 50};
printArray(myArray, 5); // 将数组名传递给函数
return 0;
}
在上述代码中,printArray 函数接受一个整数数组和数组大小作为参数,我们将 myArray 数组名传递给函数,函数内部可以像使用指针一样使用 arr 数组名。
C 中数组详解
在 C 中,数组是非常重要的,我们需要了解更多有关数组的细节。下面列出了 C 程序员必须清楚的一些与数组相关的重要概念:
概念 | 描述 |
---|---|
多维数组 | C 支持多维数组。多维数组最简单的形式是二维数组。 |
传递数组给函数 | 您可以通过指定不带索引的数组名称来给函数传递一个指向数组的指针。 |
从函数返回数组 | C 允许从函数返回数组。 |
指向数组的指针 | 您可以通过指定不带索引的数组名称来生成一个指向数组中第一个元素的指针。 |
静态数组与动态数组 | 静态数组在编译时分配内存,大小固定,而动态数组在运行时手动分配内存,大小可变。 |
HBR1
238***[email protected]
指针与数组的区别
字符数组:
字符串指针:
得出结论字符数组的 首地址可以用 arrgs ,&arrgs,来表示并且它们相等,
但是指针&str和str是不同的,当遇到字符串指针时候要注意处理方式;
HBR1
238***[email protected]
喵帕斯
115***[email protected]
一个小知识点:
在我们没有明确数组的元素个数时,在程序中想知道数组单元个数可以使用 sizeof(a)/sizeof(a[0]), sizeof(a) 是得到数组 a 的大小,sizeof(a[0]) 是得到数组 a 中单个元素的大小(因此可以不必要是a[0],a[i]都行),eg:
喵帕斯
115***[email protected]
流浪天涯
223***[email protected]
数组是一种一次申请多个变量的方法,数组的使用让我们可以在程序中保留多个变量的值,进行处理,例如给定n个学生的成绩,要求有多少学生超过了平均分,代码如下:
流浪天涯
223***[email protected]
沂圆束潇
953***[email protected]
输出结果:
事实上 a[0] 、a[1]...a[i] 代表的都是值,a、(a+0)、(a+1)、(a+i) 代表的是地址;另外这里的 a 代表整个数组的首地址,相当于 a[0] 的地址,而这里 (a+1) 就代表的是 a[0+1] 的地址。
正如文章中提到的:所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素,即是说 (a+i) 就代表的是 a[0+i] 的地址。
沂圆束潇
953***[email protected]
布克F91
335***[email protected]
对于数组的初始化需要注意以下几点:
1) 可以只给部分元素赋值,当 { } 中值的个数少于元素个数时,只给前面部分元素赋值。例如:
表示只给 a[0]~a[4] 5 个元素赋值,而后面 5 个元素自动初始化为 0。
当赋值的元素少于数组总体元素的时候,不同类型剩余的元素自动初始化值说明如下:
我们可以通过下面的形式将数组的所有元素初始化为 0:
由于剩余的元素会自动初始化为 0,所以只需要给第 0 个元素赋值为 0 即可。
2) 只能给元素逐个赋值,不能给数组整体赋值。例如给 10 个元素全部赋值为 1,只能写作:
而不能写作:
布克F91
335***[email protected]
Jiangang
121***[email protected]
指针与数组名的区别
指针:也是一个变量,存储的数据是地址。
数组名:代表的是该数组最开始的一个元素的地址。
区别:指针是一个变量,可以进行数值运算。数组名不是变量,不可以进行数值运算。
Jiangang
121***[email protected]
chrislee
cod***[email protected]
数组和指针的关系
int a[]
本质是指针 可以直接换成int *a
;[]
进行运算,而且可以通过a[0]
就直接修改了外面的数组元素;size of(a) == sizeof(int *)
所以函数内部没法用sizeof
得到数组的长度 只能传一个len
;[]
运算符可以对数组做,也可以对指针做p[0] == a[0]
;*
运算符可以对指针做,也可以对数组做*a = 25
, *a可以得到或者修改数组首个元素的值;int a[] = {1,2,5,7}
;int b[]
,由于int b[]
实质上等价于 <===> int const *b; b 是一个常数,不能被改变,初始化出来代表这个数组就不能再改变。 b = a; (错误) 数组变量之间是不可以这样互相赋值的。 而 int *q = a; 这样是可以的。chrislee
cod***[email protected]
瓜皮
410***[email protected]
数组赋值的区别:
所以比较的话,a 的大小比 a1 大,长度相同,大小不同。
瓜皮
410***[email protected]
wshisuifeng
wsh***[email protected]
数组初始化技巧: 将元素全部置零 {0}。
wshisuifeng
wsh***[email protected]
C渣渣
298***[email protected]
可将枚举、数组和结构体结合起来使用,例如输入5个人的姓名、学号、成绩,但是光靠记忆是记不住哪个人的成绩是数组中第几个元素:
这样通过索引枚举中各个人的名字作为数组中的元素位置即可快速查询某个人的成绩等信息。
C渣渣
298***[email protected]
sixwolves
liu***[email protected]
数组名是指向数组首个元素的指针常量,*a==a[0],*(a+1)==a[1],其类型应该为指向 int 类型的指针:
对数组名取地址:&a,得到的应该是整个数组的地址。这时可以认为 a 是整个数组的变量名,对变量名进行取地址操作:&,会得到该变量的地址;
操作:(&a+1) 得到的是增大整个数组内存大小的地址:增大 4*10。
sixwolves
liu***[email protected]
小菜
503***[email protected]
数组是按顺序排列的,同类型对象的集合。(下面所有如果索引0称之为第0个子元素,其他类似)
数组属于不可修改左值,因此只能初始化,无法赋值:
可以通过下标运算符 [ ] 来访问数组元素:
如果数组的每一个元素,也是一个数组类型,那么称之为二维数组(多维数组):
指针对是某类型对象地址的称呼(类型+地址)。通过&运算符创建指针。
通过 * 运算符访问指针指向的对象,称之为解引用:
数组类型的左值表达式大多数会隐适转换为首元素指针(也称之为退化),转换后的指针不是左值。数组名是数组的标识符,本身不是指针。下标运算符 [ ]不是数组运算符,用于指针和整数的运算符
。字符串字面量也是数组类型,因此大多数也会转换成首元素指针,用于初始化字符数组类型除外:
小菜
503***[email protected]