c语言中数组和数组的一些计算

本文详细介绍了C语言中的数组创建、初始化及计算,并深入探讨了指针的基本概念及其在数组中的应用。通过具体实例解释了sizeof运算符和strlen函数在不同场景下的使用方法。

1.数组的创建
元素类型 数组名 []     eg:int arr[10]
注意:[]内是一个常量表达式,用来指定数组的大小


2.数组的初始化
若指定数组大小,可以不进行初始化,若数组完全初始化后,可以不指定其大小
注意:字符串放在字符数组中,默认后面有'\0',字符数组是里面有哪些元素,就是哪些元素..


3.指针初步,指针是一个专门用来存放地址的变量,内存中一个内存单元对应一个地址,
注意:在32位平台上指针(地址)的大小始终为4个字节,64位平台上是8个字节...


4.数组的计算

维数组

(1)

int main()
{
//一维数组
int a[] = {1,2,3,4};
//size of ----一个操作符,可以求出操作数的类型长度(以字节为单位)
printf("%d\n",sizeof(a));//==16 
//本身数组名一般代表的是数组首元素的地址,但当数组名单独放在sizeof内部代表的是整个数组中全部元素,因此sizeof(a),求取的是 整个数组中所有元素的类型长度,数组中有4个整型元素,一个整型元素在内存中会占4个字节,因此求出来的类型长度为4*4==16个 字节;

printf("%d\n",sizeof(a+0));//==4
//sizeof(a+0),由以上叙述可以知道,此处sizeof后边的a代表的是数组首元素中的地址,加上0还是代表数组首元素的地址,而地址 在内存中占用的空间全部都是4个字节,因此,此处的长度为4;

printf("%d\n",sizeof(*a));//==4
//此时数组名同样没有单独放在sizeof内部,因此a代表数组首元素的地址,加上*,解引用后,表示的是此数组第一个元素--1,1作为 一个整型元素,在内存中占4个字节,因此求出的长度是4;

printf("%d\n",sizeof(a+1));//==4
//此时,a依然代表的是数组首元素的地址,加上1之后表示第二个元素的地址,地址在内存中占用的空间是4个字节,因此求出的长度 为4;

printf("%d\n",sizeof(a[1]));//==4
//a[1] == 2;2作为一个整型元素,在内存中占4个字节,因此求出的长度是4;

printf("%d\n",sizeof(&a));//==4
//&a代表的是整个数组的地址,依旧是个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;

printf("%d\n",sizeof(*&a));//==16
//&a代表的是整个数组的地址,加*号解引用后,代表的是整个数组元素,数组中有4个整型元素,一个整型元素在内存中会占4个字 节,因此求出来的类型长度为4*4==16个字节;

printf("%d\n",sizeof(&a+1));//==4
//&a代表的是整个数组的地址,&a+1指向的跳过该数组的下一个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的 长度为4;


printf("%d\n",sizeof(&a[0]));//==4
//&a[0]代表的是数组第一个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此处的长度为4;

printf("%d\n",sizeof(&a[0]+1));//==4
//&a[0]代表的是数组第一个元素的地址,&a[0]+1指向的是第二个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此 处的长度为4;

printf("%p\n",a);//==0038F9EC,数组首元素地址
printf("%p\n",a+1);//==0038F9F0,数组中第二个元素地址,与上一个元素地址差4
printf("%d\n",sizeof(*a));//==4,数组首元素地址解引用,代表数组第一个元素的值,占用4个字节的空间

printf("%p\n",&a);//==0038F9EC,虽然&a代表整个数组的地址但为了方便起见,传回来的是首元素的地址
printf("%p\n",&a+1);//==0038F9F0,&a代表整个数组的地址,+1后代表跳过数组后的那个一个地址值,与上一个差16;
printf("%d\n",sizeof(*&a));//==16,&a代表的是整个数组的地址,加*号解引用后,代表的是整个数组元素,数组中有4个整型元素,一个整型元素在内存中会占4个字节,因此求出来的类型长度为4*4==16个字节; 

return 0;
}


字符数组

(1)

int main()
{
//字符数组
char arr[] = {'a','b','c','d','e','f'};
//size of ----一个操作符,可以求出操作数的类型长度(以字节为单位)
//此时数组中元素有[a,b,c,d,e,f],一共6个元素

printf("%d\n", sizeof(arr));//==6
//数组名单独存放在sizeof中代表整个数组中所有元素,一个字符型元素在内存中占用空间1个字节,一共6个元素,因此求出的长度是6;

printf("%d\n", sizeof(arr+0));//==4
//sizeof(arr+0),此处sizeof后边的a代表的是数组首元素中的地址,加上0还是代表数组首元素的地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;

printf("%d\n", sizeof(*arr));//==1
//此时数组名同样没有单独放在sizeof内部,因此a代表数组首元素的地址,加上*,解引用后,表示的是此数组第一个元素__'a','a'作为一个字符型元素,在内存中占1个字节,因此求出的长度是1;

printf("%d\n", sizeof(arr[1]));//==1
//arr[1]代表的是第二个元素'b'个,作为一个字符型元素,在内存中占用1个字节的长度;

printf("%d\n", sizeof(&arr));//==4
//&arr代表的是整个数组的地址,依旧是个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;

printf("%d\n", sizeof(&arr+1));//==4
//&arr代表的是整个数组的地址,&arr+1指向的跳过该数组的下一个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;

printf("%d\n", sizeof(&arr[0]+1));//==4
//&arr[0]代表的是数组第一个元素的地址,&arr[0]+1指向的是第二个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此处的长度为4;
return 0;
}

(2)

int main()
{
char arr[] = {'a','b','c','d','e','f'};
//此时数组中元素有[a,b,c,d,e,f],一共6个元素
//strlen函数,参数是要开始寻找元素字符串的起始地址,返回值是字符串中字符的数量(不包括最后'\0'这个结束标志)

printf("%d\n", strlen(arr));//==随机值
//arr  代表数组首元素地址,将数组首元素地址传给strlen函数,该函数从该地址开始数数,直到碰到'\0'为止,因此输出为随机值

printf("%d\n", strlen(arr+0));//==随机值
//arr+0  代表数组首元素地址,将数组首元素地址传给strlen函数,该函数从该地址开始数数,直到碰到'\0'为止,因此输出为随机值

printf("%d\n", strlen(*arr));//==程序中断
printf("%d\n", strlen(arr[1]));//==程序中断
//上面*arr,对数组首元素地址解引用,表示第一个元素'a',而arr[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!

printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值
printf("%d\n", strlen(&arr[0]+1));//随机值
//以上三个都是因为'\0',没有在数组中,因此会显示随机值!

return 0;
}

(3)

int main()
{
char arr[] = "abcdef";
//此时数组中含有[a,b,c,d,e,f,\0]

printf("%d\n", strlen(arr));//==6
//数组首元素地址传给函数,数组中有'\0',前有6个元素!

printf("%d\n", strlen(arr+0));//==6
////数组首元素地址传给函数,数组中有'\0',前有6个元素!

printf("%d\n", strlen(*arr));//error
printf("%d\n", strlen(arr[1]));//error
//上面*arr,对数组首元素地址解引用,表示第一个元素'a',而arr[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!

printf("%d\n", strlen(&arr));//==6
//数组首元素地址传给函数,数组中有'\0',前有6个元素!

printf("%d\n", strlen(&arr+1));//==随机值
//&arr表示整个数组地址,+1表示跳过该数组后第一个地址,又在寻找'\0',所以是随机值!

printf("%d\n", strlen(&arr[0]+1));//==5
//将第二个元素地址传给函数,知道寻找到'\0',所以为5

return 0;
}

(4)

int main()
{
char *p = "abcdef";
//数组中内容[a,b,c,d,e,f,\0]
//此时把数组中首元素地址,存放在指针变量p中去了

printf("%d\n", sizeof(p));//==4
//p是数组中首元素地址,地址在内存中均占用4个字节的位置,因此为4;

printf("%d\n", sizeof(p+1));//==4
//p是数组中首元素地址,p+1表示首元素地址后面的那个地址,地址在内存中均占用4个字节的位置,因此为4;

printf("%d\n", sizeof(*p));//==1
//p是数组中首元素地址,地址解引用,表示数组第一个元素'a',他是一个字符型元素,在内存中占用1个字节;

printf("%d\n", sizeof(p[0]));//==1 == *(p+0) == *(arr+0) == arr[0yi]
//p是数组中首元素的地址,而arr也表示数组中首元素的1地址,从某种角度来说,arr[0]和p[0]是等价的,表示首元素'a',他是一个字符型元素,在内存中占用1个字节;

printf("%d\n", sizeof(&p));//==4
printf("%d\n", sizeof(&p+1));//==4
printf("%d\n", sizeof(&p[0]+1));//==4
//以上三个都是一个类型,都是取出来的地址,地址在内存中占4个字节,因此为4!

printf("%d\n", strlen(p));//==6
//将数组元素首地址传递给给函数,数组中有'\0',所以有6个元素!

printf("%d\n", strlen(p+1));//==5
//将数组元素首地址的下一个地址,也就是第二个元素的地址,传递给给函数,数组中有'\0',所以有5个元素!

printf("%d\n", strlen(*p));//error
printf("%d\n", strlen(p[0]));//error
//上面*p,对数组首元素地址解引用,表示第一个元素'a',而p[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!

printf("%d\n", strlen(&p));//随机值
//&p表示对指针变量再取地址传入函数中,而中从此处开始查找的时候,后面并没有'\0',所以是随机值

printf("%d\n", strlen(&p+1));//随机值
//&p表示对指针变量再取地址,然后这个地址的下一个地址传入函数中,而中从此处开始查找的时候,后面并没有'\0',所以是随机值

printf("%d\n", strlen(&p[0]+1));//==5
////将数组元素首地址的下一个地址,也就是第二个元素的地址,传递给给函数,数组中有'\0',所以有5个元素!

return 0;
}


### 数组大小与数组深度的定义 在C语言中,**数组大小**通常指的是数组中元素的总数量,可以通过 `sizeof(arr)/sizeof(arr[0])` 的方式计算得出。例如,一个 `int arr[4]` 的数组,其大小为4,表示数组中包含4个整型元素。这一计算方式适用于静态数组,因为 `sizeof` 在编译时能够确定数组的总字节数,并据此推出元素个数[^1]。 而**数组深度**则是指数组的维度数量。例如,一维数组 `int arr[4]` 的深度为1,二维数组 `int arr[3][4]` 的深度为2,三维数组 `int arr[2][3][4]` 的深度为3。每个维度的大小决定了该维度上可以存储的元素数量,例如 `int arr[3][4]` 表示一个包含3行、每行4列的二维数组数组的深度决定了访问数组元素时需要提供的索引数量,例如访问二维数组的元素需要两个索引值 `arr[i][j]`,分别表示行列的位置[^2]。 ### 数组大小与数组深度的计算方式 数组的大小可以通过 `sizeof` 运符进行计算,例如: ```c int arr[4]; int size = sizeof(arr) / sizeof(arr[0]); // size = 4 ``` 上述代码中,`sizeof(arr)` 返回数组的总字节数(4个整型,每个整型占4字节,共16字节),`sizeof(arr[0])` 返回单个整型的大小(4字节),两者相除即可得到数组的大小(即元素个数)。 而对于多维数组数组的深度则由其声明的维度决定。例如,二维数组 `int arr[3][4]` 的深度为2,表示它是一个二维结构。可以通过 `sizeof(arr)/sizeof(arr[0])` 来计算第一维的大小(即行数),而 `sizeof(arr[0])/sizeof(arr[0][0])` 可以计算第二维的大小(即列数): ```c int arr[3][4]; int rows = sizeof(arr) / sizeof(arr[0]); // rows = 3 int cols = sizeof(arr[0]) / sizeof(arr[0][0]); // cols = 4 ``` 上述代码中,`sizeof(arr)` 返回整个数组的大小(3行 × 4列 × 4字节 = 48字节),`sizeof(arr[0])` 返回一行的大小(4列 × 4字节 = 16字节),两者相除得到行数;`sizeof(arr[0])` 返回一行的大小,`sizeof(arr[0][0])` 返回一个整型的大小(4字节),两者相除得到列数。 ### 数组大小与数组深度的实际影响 数组的大小直接影响程序运行时的内存使用情况。例如,一个 `int arr[1000]` 将占用4000字节(每个整型占4字节),而一个 `int arr[1000][1000]` 则将占用4,000,000字节。因此,在程序设计中,必须合理控制数组的大小,以避免不必要的内存浪费。 数组的深度则影响程序的逻辑结构访问方式。一维数组适用于线性数据的存储,例如一组学生的成绩;二维数组适用于表格形式的数据,例如矩阵运;三维数组则适用于更复杂的数据结构,例如三维空间的坐标表示。数组的深度越高,访问元素时所需的索引越多,逻辑结构也越复杂。因此,在设计程序时,应根据实际需求选择合适的数组维度[^3]。 ### 数组大小与数组深度的注意事项 在C语言中,数组的大小必须在编译时确定(C99及之后版本支持变长数组,但需谨慎使用)。如果使用指针来访问数组,`sizeof` 将无法正确计算数组的大小,因为它只会返回指针本身的大小(32位系统为4字节,64位系统为8字节)。例如: ```c int arr[4]; int *p = arr; int size = sizeof(p) / sizeof(p[0]); // 错误:p 是指针,sizeof(p) 为指针大小 ``` 上述代码中,`sizeof(p)` 返回的是指针变量的大小(4或8字节),而不是数组的总大小,因此 `sizeof(p)/sizeof(p[0])` 无法正确计算数组的大小。因此,在使用指针操作数组时,必须手动记录数组的大小,或者使用其他方式传递数组长度信息。 此外,数组的深度也会影响内存的连续性。一维数组在内存中是连续存储的,地址由低到高排列;二维数组同样以行优先的方式存储,即先存储第一行的所有元素,再存储第二行的所有元素,以此类推。例如: ```c int arr[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; ``` 上述代码中,数组在内存中的存储顺序为:1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12。这种连续存储方式使得数组的访问效率较高,但也要求程序员在操作数组时注意内存越界问题。数组的深度越高,越容易出现越界访问,例如访问 `arr[3][4]` 会导致非法内存访问,因为数组的有效索引范围是 `arr[0][0]` 到 `arr[2][3]`。C语言本身不进行数组越界检查,因此必须由程序员自行确保索引的合法性[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值