IOS学习第12天
二维数组
- 二维数组在内存中的存储
1.二维数组在内存中也是”从高到低申请连续内存的”,一共有行 * 列 * sizeof(单个元素的数据类型)
2.第0行是在”低”字节
- 二维数组的地址和行列计算
1.二维数组的地址 == 二维数组名 == 二维数组的低地址 == 二维数组中第0行的地址 == 二维数组中第0行第0个元素地址
== 二维数组第0行的低字节地址
2.二维数组的长度以及行列计算
长度:二维数组的总字节数 / 单个元素的字节数
sizeof(二维数组名) / sizeof(单个元素的字节数)
行数:二维数组的总字节数 / 每一行的字节数
sizeof(二维数组名) / sizeof(二维数组名[0])
列数:每一行的字节数 / 单个元素的字节数
sizeof(二维数组名[0]) / sizeof(单个元素的字节数)
- 二维数组与函数
1.当二维数组作为函数的参数的时候,会丢失这个二维数组的行数和列数
2.当而为驻足作为函数的参数的时候,行数可以省略,要保证实参二维数组的列数必须要和形参二维数组的列数相同
3.写参数的时候,可以先写行数和列数,最后再写二维数组,然后二维数组的列数用参数的列数来决定
void fuZhi(int row,int col,int nums[][col])
{
//函数体:给nums这个数组中的每一个元素赋值
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
//nums[i][j]
nums[i][j] = i*j+10;
}
// printf("\n");
}
}
字符串
- 原理
将字符串数据的每1个字符存储到字符数据中,并在后面追加1个’\0’来表示存储完毕
- 格式
1>最基本的方式:
char name[10] = {'a','b','c','\0'};
2>最简单的方式:
char name[30] = {"abc"};//看成 字符串 "abc" 是四个字符 分别是'a''b''c''\0'
字符串可见长度:3
字符串实际长度:4
数组的长度: 30
一般来说 如果问 一个字符串的长度是多少?那么就是指的 实际长度
3>最常用的方式:
char name[] = "abc";
"字符串可以看成一个字符数组 "abcd"
"但是 字符数组 不一定是字符串
char name[4];
name[0] = 'a';
name[1] = 'b';
name[2] = 'c';
name[3] = 'd';
一个小题:
char name[20] = {'j','a','c','k'}; 可以看成字符串 "jack"
char name[20] = {'j','a','\0','k'}; 可以看成字符串 "ja"
char name[10];
name[0] = 'j';
name[1] = 'a';
name[2] = 'c';
name[3] = 'k';
不能,因为k后面虽然后字符,但是不一定是'\0'
char name[4] = {'j','a','c','k'};不能,末尾没有'\0'
char name[4] = {"jack"}; 不能,末尾的'\0'已经超出了数组范围
```
* 使用字符数组存储字符串注意的地方
1.如果没有指定的长度,给数组赋值一个字符串的时候,那么数组的长度是字符串的可见长度+1
2.如果指定的字符数组的长度小于等于了字符串的长度,这个时候就会有问题
3.C语言中一个中文字符占3个字节
* 使用%s输出存储在字符数组中的字符数据
使用%s格式控制符,就可以输出存储在字符数组中的字符串数据
原理:从给定的地址开始,1个字节1个字节的输出,指导遇到'\0'为止
缺点:
1.如果你要打印的字符串中间有'\0',那么只会打印'\0'前面的部分
2.输入的字符串中间不能有空格,如果有空格,只能存储"空格"之前的字符串
* 字符串长度的计算
int len = 0;
char str[] = “aasdladjkwe”
while(str[len] != ‘\0’)
{
len++;
}
printf(“字符串的长度为”)
* 与字符串相关的函数
| 函数名 | 参数 | 作用 |
| -- | -- | -- |
| puts() | const char * | 输出字符串 |
| gets() | char * | 控制台获取输入的字符串 |
|strlen() | const char * | 计算字符串的可见长度 |
| strcmp() | const char *, const char * | 比较两个字符串的大小 |
| strcpy()| char *, const char *| 拷贝字符串 |
| strcat() | char *, const char * | 连接两个字符数组 |
### 指针
* 指针变量的声明
1.什么叫指针变量
一个变量,用来保存另外一个变量的地址
如果一个指针变量p 存储了 另外一个变量num的地址
那么我们称 这个指针变量 指向了 num变量
存储了谁的地址 就指向了谁
2.指针变量有啥用?
可以通过指针变量,间接 访问/修改/获取 它所指向的变量中数据
3.如何声明一个指针变量?**
语法:数据类型 * 指针变量名
int * p1;定义了一个指针变量 变量名叫p1,说明这个p1变量 能存int类型变量的地址
4.不同类型的指针变量,存储对应类型的变量的地址
* 指针变量的初始化
1.什么叫指针变量
一个变量,用来保存另外一个变量的地址
如果一个指针变量p 存储了 另外一个变量num的地址
那么我们称 这个指针变量 指向了 num变量
存储了谁的地址 就指向了谁
2.指针变量有啥用?
可以通过指针变量,间接 访问/修改/获取 它所指向的变量中数据
3.如何声明一个指针变量?**
语法:数据类型 * 指针变量名
int * p1;定义了一个指针变量 变量名叫p1,说明这个p1变量 能存int类型变量的地址
4.不同类型的指针变量,存储对应类型的变量的地址
* 指针变量的使用
1.如何 使用指针变量 操作它所指向的变量的数据
int num = 10;
int *p_num = #//这里的*代表 p_num是一个指针变量
通过p_num指针间接操作指针指向的变量
*p_num; //这里的*代表 解析地址 解析出来就是num变量
打印:printf("%d",*p_num);
赋值:*p_num = 200;
* 野指针
.什么是野指针:
乱指的指针,指针变量中存储的值 是一个垃圾值
int num;//垃圾值
int * p_num;//垃圾地址
这个指针就是野指针
定义一个指针 但是没有给他赋初始值,那么这个指针就是野指针
2.定义一个野指针
int *p_num;
*p_num = 50;//非法操作
野指针 如果随便访问 那么会遇到 难以预料问题
“`
* NULL值
1.
int num = 0;//定义一个变量 如果不知道初始值,给他赋值一个0
int *p_num = NULL;//如果定义一个变量,不知道初始值是什么,那么我们会给他一个默认值 NULL
*p_num = 50;//会 100%报错
2.如果1个指针变量的值是NULL值.这个时候通过指针变量去访问指向的变量的时候 100%报错.(没有意义)
结论: 只要是申明了一个指针 不知道初始值
那么 我们这么干 int *p_num = NULL;
```
* 多个指针指向同一个变量
int num = 10;
int* p1 = #
int* p2 = p1;p1和p2指针都指向了num变量.
2.练习:
int num1 = 10;//num1 的地址 0x1101
int num2 = 20;//num2 的地址 0x1102
int * p_num1 = &num1;// p_num1 里面的值 0x1101
p_num1 = &num2;//p_num1 里面的值 0x1102
*p_num1 = 30;//num2 = 30;
printf("num1 = %d,num2= %d\n",num1,num2);
* 指针作为函数的参数
**指针作为函数的参数是地址传递,在函数内部,如果改变了地址中变量的值,那么调用者中的变量值也会一样改变**
**一个函数具有多个返回值**
1.这个函数返回值有2个 但是一个函数只有一个返回值
2.就会想到指针,在主调函数中定义两个变量
3.把这两个变量的地址 作为参数传递给函数
4.在函数内部求出最大值最小值之后,将它们分别赋值给 这两个地址解析后的变量里
5.那么函数调用完之后,主函数中的变量的值也会跟着改变
“`