1. 数组的地址
1.1 一维数组的地址
int a[5];
(1)
&a[0] | 第0个元素的地址 |
a | 第0个元素的地址 |
&a | 整个一维数组的地址 |
(2)&a[0] == a == &a;
(3)
&a[0] + 1 | 跳过一个数组元素 |
a + 1 | 跳过一个数组元素 |
&a + 1 | 跳过整个数组 |
1.2 二维数组的地址
int a[2][3];
(1)
&a[0][0] | 0行0列元素的地址 |
a[0] | 0行一维数组的地址 |
a | 0行一维数组的地址 |
&a | 整个二维数组的地址 |
(2)&a[0][0] == a[0] == a == &a;
(3)
&a[0][0] + 1 | 跳过一个数组元素 |
a[0] + 1 | 跳过一个数组元素 |
&a[0] + 1 | 跳过一个一维数组 |
a + 1 | 跳过一个一维数组 |
&a + 1 | 跳过整个数组 |
2. 二维数组行列数求法
示例:
int a[3][4] = { 1, 2, 3 }; // 定义二维数组
/**********************************************************************/
sizeof(a) / sizeof(a[0][0]); // 元素个数 = 数组大小 / 一个元素的大小
sizeof(a) / sizeof(a[0]); // 行数 = 数组大小 / 一行的大小
sizeof(a[0]) / sizeof(a[0][0]); // 列数 = 一行的大小 / 一个元素的大小
3. 字符数组
char a[5] = { 'a', 'b', 'c', 'd', 'e' }; // 普通字符数组
printf("%s\n", a); // 乱码,因为没有'\0'结束标志char b[5] = { 'a', 'b', 'c', 'd', '\0' }; // 字符数组中含有'\0',就是字符串,与下面一行等价
char c[5] = "abcd"; // 字符串,存的是"abcd\0"
3.1 从键盘读取字符串
3.1.1 scanf
char num[5] = "";
scanf("%s", num);
printf("%s", num);
运行结果:
输入“12 12”,则只会输出“12”。
scanf缺点:
(1)不会读入空格、'\n',而是停止读取;
(2)存放读取字符的空间不足,仍会继续将字符读入后面的内存空间,造成内存污染;(可使用scanf_s避免该问题,如下)
char num[5] = "";
scanf_s("%s", num, 5); // 第三个参数限制只能读入5个字符
printf("%s", num);
注意:本例中scanf_s第3个参数“5”表示num字符数组能存5个字符,包括末尾自动添加的‘\0’,因此人为输入的最大字符数为4.
3.1.2 gets
char num[5] = "";
gets(num);
printf("%s", num);
运行结果:
优点:
(1)会读入空格,但不会读入‘\n’,遇到'\n'会停止读取;
缺点:
(1)存放读取字符的空间不足,仍会继续将字符读入后面的内存空间,造成内存污染;(可使用scanf_s避免该问题,如下)
char a[5] = "";
gets_s(a, 5); // 第三个参数限制只能读入5个字符
printf("%s", a);
注意:gets、gets_s也会在末尾自动添加'\0'。
3.1.3 fgets
fgets是库函数,从键盘读取一个字符串;
char a[5] = "";
fgets(a, sizeof(a), stdin);
printf("%s", a);
该示例中,fgets将字符串从标准输入读入a中,最大读入sizeof(a)-1个,末尾自动添加'\0'.
优点:
(1)会读入空格、'\n';但读入'\n'后会停止读取;
(2)指定读入的字符个数,避免内存污染问题。
3.2 字符串的输出
3.2.1 puts
char buf[1024] = "Hello World";
puts(buf); // 最后会输出换行
3.2.2 fputs
char buf[1024] = "Hello World";
fputs(buf, stdout); // 不会输出换行