关于数组
-
C编译器不会检查数组的下标是否正确,而一般这种错误,会导致数据被放置在已被其他数据占用的地方,可能会破坏程序的结果、或导致程序异常中断(segment fault)
float debts[20]; debts[20] = 88.32; //这样的错误,编译器是找不出来的
-
char型数组末尾包含空字符**‘\0’**,那数组的内容就构成一个字符串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F0RtQ5oD-1661656316691)(关于数组.assets/image-20220807222425893.png)]
-
scanf会跳过空白字符
-
⭐️模块化设计:就是把程序划分为一些独立的单元,每个单元执行一个任务
-
在c语言中,main()通常只提供整个程序的框架,最好把main()放在所有函数定义的前面
- 这个意思就是,你把可以把函数的声明放在main函数前面(或头文件里),但是函数的定义,你要放在main函数的下面
-
要设置只读数组,加const即可,记得初始化
-
数组初始化用的数值少于数组元素个数时,编译器把剩余元素都初始化为0
-
初始化数组时,数组大小是可以省略的,这时⭐️编译器会根据初始化列表中的项数来确定数组的大小
-
计算数组大小公式:sizeof(days) / sizeof(days[0])
-
二维数组的初始化方法差异
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SVp5l3qE-1661656316695)(关于数组.assets/image-20220808215436668.png)]
-
⭐️数组名是该数组首元素的地址
-
⭐️在c中,指针加1指的是增加一个存储单元。
- 换句话说就是:指针加1,指针的值递增它所指向类型的大小
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A5SFJkz4-1661656316696)(关于数组.assets/image-20220808215721576.png)]
-
许多计算机都是按字节编址,就是说内存中的每个字节都是按顺序编号的,比如double类型的变量,他的地址通常是该对象第一个字节的地址
-
在使用数组作为函数参数的时候,最好带上数组的大小作为参数
int sum(int ar[], int n) // 这样的写法比 int sum(int *ar)更好,使用 int sum(int *ar, int n)也是可以的 { int i = 0; int total = 0; for (; i < n; ++i) { total += ar[i]; } return total; }
-
C保证在给数组分配空间时,指向数组后面第一个位置的指针仍是有效指针
#define SIZE 10 int marbles[SIZE] = {26, 29, 0}; int answer = sump(marbles, marbles + SIZE); int sump(int *start, int *end) { int total = 0; while(start < end) { total += *start; //把数组元素值加起来 start++; // c的机制保证了指针指向数组后面下一个的时候,是有效的 } return total; }
-
total += *start++; //循环体内的简化版操作 //建议写成 total += *(start++);
- ⭐️ 一元运算符*和++的优先级相同,但结合律是从右往左, 所以显示start++,再才是*start,
- 先把指针指向位置上的值加到total上
- 在递增指针
- ⭐️ 如果使用*++start,则
- 先递增指针
- 再使用指针指向位置上的值
- ⭐️ 如果使用(*star)++
- 先使用指针指向的值
- 在递增该值(不是递增指针)
- 就是说指针一直指向同一个位置,但是该位置上的值发生了变化
- ⭐️ 一元运算符*和++的优先级相同,但结合律是从右往左, 所以显示start++,再才是*start,
-
⭐️数组名是不能做自增操作的,因为数组名虽然是指针,但是它是一个常量,常量是无法修改的
-
针对一个处理基本类型(如int)的函数时,会面临两种选择
- 传递int类型的值
- 传递指向int的指针
- ⭐️ 通常都是直接传递数值,只有需要在函数中改变该数值时,才会传递指针
-
一般而言,在把数组作为函数参数时
- 需要修改数组—在声明数组形参时不使用const
- 不需要修改数组—在声明时加上const
-
const指针:指向const、指向非const都是合法的
-
非const指针:只能指向非const
-
关于多维数组
int zippo[4][2]
- int zippo[4][2]:可以看做zippo是一个内涵4个元素的数组,每一个元素,含有2个int型元素
- 最关键的就是指针的指向
- zippo = &zippo[0] = &zippo[0][0]
-
使用二维数组作为形参
-
int array[3][4]; /*第一个形参只描述了它是一个二维函数,且每一列都有4个,但是行数你不知道*/ void func(int (*p)[4], int rows); void func(int pt[][4], int rows);//空的方括号表示pt是一个指针
-
//这种写法是错误的 //因为在编译的时候,编译器会把数组表示法转换成指针表示法 //ar[1]转换成ar+1,编译器对ar+1求值,要知道ar所指对象的大小 int sun2(int ar[][], int rows); int sun2(int ar[][4], int rows);//有效,ar+1,就是"该地址加上16字节" //你可以理解为ar[]就是ar指针,后面的括号是用于描述ar指针所指向数据对象的类型
-
c里规定,数组的维数是固定的,不能用变量来代替COLS(列数)
-
-
使用变长数组的特性
-
变长数组中的变,指的是:在创建数组时,可以使用变量指定数组的维度。而不是说可以随意修改已创建数组的大小
-
int sum(int rows, int cols, int ar[rows][cols]);//有效 int sum(int ar[row][cols], int rows, int cols); //无效,因为ar的声明要使用rows和cols,所以在形参列表中必须在声明ar前先声明这两个形参
-
-
c把数组名解释为该数组首元素的地址。换言之,数组名与指向该数组首元素的指针等价。
-
在C语言里,不能将整个数组传递给函数,但是可以传递数组的地址,然后借由函数地址操作原数组
-
如果在函数中,没有修改原数组的意图,应在声明函数的形式参数时使用功能关键字const
-
指针加上一个整数或递增指针,指针的值以所指向对象的大小为单位改变