最近,想复习一下C语言,所以笔者将会在掘金每天更新一篇关于C语言的文章! 各位初学C语言的大一新生,以及想要复习C语言/C++知识的不要错过哦! 夯实基础,慢下来就是快!
1.数组基本概念
01:数组未给定大小时,是以初始化的个数 确定 数组的大小
int arr[] = {1,2,3}; //数组大小为3 复制代码
02.数组不完全初始化,剩余的元素初始化为0
int arr[5] = {1,2,3}; 复制代码
03.字符数组是否存放\0的问题
写法1:char arr[] = "abcde"; //数组arr的大小为6 字符串长度为5 含\0 复制代码
写法2:char arr[] = { 'a','b','c','d','e' };//数组arr的大小为5 并没有放\0进去 复制代码
04.数组创建不可以即不初始化也不指定大小
int arr[]; //err 复制代码
05:一维数组和指针
int arr[5] = {0}; int *p = arr; int**pp = &arr; //数组名是首元素地址,首元素为int类型,&数组名类型为int**类型 *(p+i) == arr[i] == p[i] 复制代码
06:数组越界时的报错--Stack around the variable 'arr' was corrupter
int main() { int arr[10] = {0}; printf("%d\n", arr[10]);//这样不会报错,因为只是得到越界的空间的值 arr[10] = 0;//这样会报错,因为是对越界空间的值的修改 } 复制代码
2.局部变量不初始化和全局变量不初始化
全局变量:放在存放在静态存储区,在程序开始执行时给全局变量分配存储区,程序行完毕就释放。 不初始化:默认为0 局部变量:存放在栈区 不初始化:默认为随机值 复制代码
在数组中的体现
3.二维数组
01:二维数组的行可以省略,列不可以省略
02:在初始化的情况下才可以省略行,在未初始化时,不可以省略
int arr[][5]; //err 复制代码
03:二维整形数组
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 }; //3行3列 //相当于 //int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; 复制代码
//二维数组当成一位数组理解 int main() { int arr[3][3] = { 1,2,3,4,5,6,7,8,9 }; int* p = &arr[0][0]; int i = 0; for (i = 0; i < 9; i++) { printf("%d ",*p); p++; } return 0; } 复制代码
04:二维字符数组
char arr[3][5] = { "Mango","Lemon","shuai"}; 复制代码
原因:每一个字符串后面都没有放\0
//正解: char arr[3][6] = { "Mango","Lemon","shuai"}; 复制代码
对于二维字符数组**,列的大小应该取决于存放的最长的字符串的长度+1,不然就放不下\0,造成越界访问!**
如:char arr[3][10] ={"a","abcdefdwo","b"}; 复制代码
4.冒泡排序
10个数字只需要进行 9次冒泡排序即可 原因:每一次冒泡排序可以让1个元素来到应该出现的位置,排了9次,搞定9个数字,则剩下的1个必然在应该在的位置上 每一趟可以少比较一个元素 10个元素,第一趟比较9对数字,第二趟比较8对....... 复制代码
代码
//交换两个值->传址 void Swap(int* pa, int* pb) { int tmp = *pa; *pa = *pb; *pb = tmp; } void BubbleSort(int* arr, int sz) { int i = 0, j = 0; //排序n—1趟 for (i = 0; i < sz-1; i++) { //每次排序可以少比较一个元素 for (j = 0; j < sz - 1 - i; j++) { //排成升序 即前一个比就一个大 if (arr[j] > arr[j + 1]) { Swap(&arr[j], &arr[j + 1]); } } } } int main() { int arr[10] = { 9,5,6,3,6,7,9,0,3 ,2}; int sz = sizeof(arr) / sizeof(arr[0]); BubbleSort(arr, sz); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } return 0; } 复制代码
优化版
优化版冒泡排序:
当第某一趟冒泡排序没有进行交换时,说明已经时有序的了
//交换两个值->传址 void Swap(int* pa, int* pb) { int tmp = *pa; *pa = *pb; *pb = tmp; } void BubbleSort(int* arr, int sz) { int i = 0, j = 0; //排序n—1趟 for (i = 0; i < sz-1; i++) { int flag = 1;//假设已经有序-- //要放在for循环内部---每一趟进去都假设有序 //每次排序可以少比较一个元素 for (j = 0; j < sz - 1 - i; j++) { //排成升序 即前一个比就一个大 if (arr[j] > arr[j + 1]) { Swap(&arr[j], &arr[j + 1]); flag = 0;//无序 } } //若恒为1,说明已经有序了 if(flag == 1) { break; } } } int main() { int arr[10] = { 9,5,6,3,6,7,9,0,3 ,2}; int sz = sizeof(arr) / sizeof(arr[0]); BubbleSort(arr, sz); int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } return 0; } 复制代码
定义一个标志变量
若此次冒泡排序要进行交换,则说明无序,令flag = 0,
再次进行下一趟冒泡排序时,再令flag=1,继续判断是否要交换,若此次不需要交换了(flag 恒为1),说明已经有序了,break跳出
5.关于数组名的理解
数组名表示整个数组的情况 1.数组名单独放在sizeof内部,sizeof(数组名)-> 此时数组名表示的是整个数组,此时sizeof(数组名)-计算的是整个数组的大小 2.&数组名 ->此时数组名表示的是整个数组 复制代码
其余情况下,数组名代表的是数组首元素地址
arr 和 &arr[0] :代表的都是首元素地址
&arr:代表的是整个数组的地址
指针+1的步长:取决于指针指向数据的类型
&arr+1 :跳过整个数组
&arr[0] + 1 :跳过一个元素,第二个元素地址
arr + 1 :跳过一个元素,第二个元素地址
数组名再传递给参数的时候,会降级变成首元素地址
数组传参-实际上传过去的是数组首元素地址
void Print(int* arr, int sz) { int i = 0; for(i = 0; i < sz; i++) { //方法1 //printf("%d ", arr[i]); //方法2 //printf("%d ", *(arr + i)); //方法3 printf("%d ", *arr++); //等价于-> *arr++ -> 相当于先解引用,再++ *arr; arr++; //++的优先级比*高 但由于是后置++,所以*p++可以 } } int main() { int arr[10] = { 9,8,7,6,5,4,3,2,1,0}; int sz = sizeof(arr) / sizeof(arr[0]); Print(arr, sz); return 0; }