一维数组
两个知识点:一是初始化,二是地址相关。
初始化
#include <stdio.h>
// int a[5]; 未初始化的全局数组变量是0
int main()
{
/*
错误示范:
int k = 5;
int a[k] = {0};
原因:定义数组的时候,长度一定要确定
*/
//int a[5]; 未初始化的局部变量是垃圾值
//int a[5] = {1,2,3}; 局部初始化,其余为0
//静态初始化:值定空间
int a[] = {1,2,3,4,5};
//动态初始化:默认值为0;
int b[5] = {0};
//数组类型 数组名 [数组元素的个数]
//数组下标是从0开始,即int a[5]里有a[0]~a[4]五个元素。
return 0;
}
地址相关
printf("%p\n", &a[0]); //数组首元素地址
printf("%p\n", a); //数组名,也是数组首元素地址 等价于&a[0]
printf("%p\n", &a); //数组的地址
上述三者输出的地址虽然一样,但意义不同(见上面注释)。
printf("%p\n", &a[0] + 1);//+1后是数组首元素地址直接加4个字节
printf("%p\n", a + 1);//+1后是数组首元素地址直接加4个字节
printf("%p\n", &a + 1);//+1后是数组地址加了20个字节
//a++; //数组名是常指针,不能修改
此处地址加的字节和数组类型有关(int类型长度为4个字节)。
二维数组
#include <stdio.h>
int main()
{
//int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; 两行三列
//int a[2][3] = {{1}, {4, 5}};部分元素初始化 未初始化为0
//int a[][3] = {{1, 2, 3}, {4, 5, 6}};//行可以不初始化,但列一定要有。
int a[2][3] = {0};
printf("%p\n", &a[0][0]);
printf("%p\n", a[0]); //表示数组首行首元素地址 和&a[0][0]一样 a[1]第二行首元素地址
printf("%p\n", a); //a 数组名 表示首行地址
printf("%p\n", &a); //&a表示数组的地址
//上面输出的四个地址一样,但含义不一样。
printf("%p\n", &a[0][0] + 1); //显示首行首元素地址加了4个字节
printf("%p\n", a[0] + 1); //显示首行首元素地址加了4个字节
printf("%p\n", a + 1);// 首行地址+加了12个字节
printf("%p\n", &a + 1);//数组地址+24个字节(加了整个数组的大小)
return 0;
}
字符数组
#include <stdio.h>
int main()
{
//char a[10] = {'h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd'};
char a[15] = "helloworld";
printf("%s\n", a); //输出字符串,遇到\0结束
//如果char a大小改为10,即大小刚刚好时,printf输出会携带其他垃圾值,大于内容时就不会。
return 0;
}
附
综上,重点在于接触了解地址相关问题,为后面指针学习打下基础。
另,至此明白了为何scanf取值给数组时不用加取地址符&(因为数组名本身就代表地址)