"痛苦难以避免,而磨难可以选择。"-->村上春树
作者:Mylvzi
文章主要内容:数据在内存中的存储
核心:
1.对于数组名的理解:数组名是数组首元素的地址(二维数组的数组名就是第一行的地址),但有两个例外,一是单独出现在sizeof内部,表示整个数组的大小,二是&数组名,代表存放整个数组的地址;
2.理解sizeof只关注()的数组类型,是地址,大小就为4/8;关注()的数据类型(数组的数据类型就是去掉数组名)
3.理解指针变量存储字符串的本质-->存储字符串首元素的地址
4.理解二维数组的元素构成,即二维数组是一维数组的数组;
5.理解数组与指针之间的的等价关系;arr[1]-->*(arr+1) *arr-->*(arr+0)-->arr[0]
6.理解strlen函数的本质即参数类型,本质是计算\0之前的字符个数,参数是const char*,是一个地址,也就是说strlen是从你传的地址作为首地址,一直向后读取字符个数,直到遇到\0;当()是元素时,会从其对应的ascii码值所在的地址访问,造成非法访问,报错
int main()
{
/*一维数组*/
//数组名代表数组首元素地址,但有两个例外
//1.sizeof数组名,计算的是整个数组的大小(数组名单独放在sizeof内部)
//2.&数组名,代表整个数组的地址
//sizeof 只关注类型,要分清代表的是元素还是地址
//对于指针,我们要关注他的指向,也就是存放的地址;其大小是固定的
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//16 ->int [4]
printf("%d\n", sizeof(a + 0));//这里的a是数组首元素的地址,+0还是数组首元素的地址,大小为4/8byte
printf("%d\n", sizeof(*a));//数组首元素,是元素,4(int类型)
printf("%d\n", sizeof(a + 1));//第二个元素的地址,是地址,大小为4/8byte
printf("%d\n", sizeof(a[1]));//第二个元素,是元素,大小为4
printf("%d\n", sizeof(&a));//&a也是地址,是地址,4/8byte
printf("%d\n", sizeof(*&a));//16 等价于sizeof(a)
//&a 是数组的地址,是一个数组指针变量,类型为int(*)[4],解引用就是访问4个int类型的元素
printf("%d\n", sizeof(&a + 1));//地址,大小为4/8byte
printf("%d\n", sizeof(&a[0]));//地址,大小为4/8byte
printf("%d\n", sizeof(&a[0] + 1));//地址,大小为4/8byte
/*字符数组*/
/*char arr[] = { 'a','b','c','d','e','f' };*/
printf("%d\n", sizeof(arr));//数组名在sizeof内部,计算整个数组的大小,6
printf("%d\n", sizeof(arr + 0));//是地址,大小为4/8
printf("%d\n", sizeof(*arr));//代表字符a,大小为1
printf("%d\n", sizeof(arr[1]));//代表字符b,大小为1
printf("%d\n", sizeof(&arr));//是地址,大小为4/8
printf("%d\n", sizeof(&arr + 1)); //是地址,大小为4 / 8
printf("%d\n", sizeof(&arr[0] + 1));//是地址,大小为4/8
//strlen的参数是const char* ,计算的是\0之前的字符个数
printf("%d\n", strlen(arr));//随机值
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen(*arr));//err strlen的参数是一个指针,是地址,*arr,相当于将a的地址传了过去,以97为起始地址,属于非法访问内存
printf("%d\n", strlen(arr[1]));//err 同上
printf("%d\n", strlen(&arr));//随机值 &arr的值和arr的值是一样的,都指向数组首元素地址
printf("%d\n", strlen(&arr + 1));//随机值 数组最后一个元素的下一位的地址
printf("%d\n", strlen(&arr[0] + 1));//随机值 从数组第二个元素开始打印字符串
//sizeof只关注类型,传arr是数组,数组的类型是去掉数组名
// 对于sizeof来说,只需注意他是地址还是普通元素
char arr[] = "abcdef"; //a b c d e f \0
printf("%d\n", sizeof(arr));//数组类型:char [7]; -->7
printf("%d\n", sizeof(arr + 0));//4 地址
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4 本质是一个地址
printf("%d\n", sizeof(&arr + 1));//4 地址
printf("%d\n", sizeof(&arr[0] + 1));//4 地址
printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr + 0));//6
printf("%d\n", strlen(*arr));//非法访问内存
printf("%d\n", strlen(arr[1]));//同上
printf("%d\n", strlen(&arr));//6
printf("%d\n", strlen(&arr + 1));//随机值
printf("%d\n", strlen(&arr[0] + 1));//5
//利用字符指针存储字符串-->指针内存储的是字符串首字符的地址
const char* p = "abcdef";
printf("%d\n", sizeof(p));//4 地址
printf("%d\n", sizeof(p + 1));//4 地址
printf("%d\n", sizeof(*p));//1 元素
printf("%d\n", sizeof(p[0]));//p[0]->*(p+0)->*p 1
printf("%d\n", sizeof(&p));//&p->char** 4
printf("%d\n", sizeof(&p + 1));//&p,char**,+1,注意此处的指针变量与数组无关
//存储的是P本身的地址 4
printf("%d\n", sizeof(&p[0] + 1));//4 -->b的地址
printf("%d\n", strlen(p));//6
printf("%d\n", strlen(p + 1));//5
printf("%d\n", strlen(*p));//err
printf("%d\n", strlen(p[0]));//err
printf("%d\n", strlen(&p));//随机值
printf("%d\n", strlen(&p + 1));//随机值
printf("%d\n", strlen(&p[0] + 1));//5
/*二维数组*/
//学会数组中的等价关系
// 给定arr是数组名(一维,二维皆可)
//arr[1]-->*(arr+1)
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//计算整个数组的大小,3*4*4 48
printf("%d\n", sizeof(a[0][0]));//4
printf("%d\n", sizeof(a[0]));//4*4=16 a[0]是一个一维数组的地址,类型为int(*)[4]
//a[0]是第一行一维数组的数组名,单独出现在sizeof内部,计算整个一维数组的大小
printf("%d\n", sizeof(a[0] + 1));//4 a[0]是第一行一维数组的数组名,没有单独出现在sizeof内部
//所以代表第一行一维数组的首元素的地址-->a[0][0]
//a[0][0]+1 就是a[0][1]的地址,是一个指针变量;一定要注意指针指向
printf("%d\n", sizeof(*(a[0] + 1)));//4 计算的就是第一行第二个元素的大小
printf("%d\n", sizeof(a + 1));//4
//a是二维数组名,是第一行的地址,存的时候是通过数组指针存放的int(*)[4]
//a+1是第二行的地址,是一个指针变量
printf("%d\n", sizeof(*(a + 1)));//16
//*(a+1)-->a[1] sizeof(*(a+1))-->sizeof(a[1]) int[4]
printf("%d\n", sizeof(&a[0] + 1));//4 是第二行一维数组的地址,本质是一个地址
//&a[0]是第一行的地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16 是对第二行整个一维数组解引用
//计算第二行整个一维数组的大小
printf("%d\n", sizeof(*a));//16 a是二维数组数组名,代表二维数组第一行的地址
//*a就是对第一行解引用,计算第一行整个一维数组的大小
//*a-->*(a+0)-->a[0]-->sizeof(a[0])
printf("%d\n", sizeof(a[3]));//16-->a[3]是一个一维数组,数组类型为int[4]
//sizeof只关注()内的数据类型,只关注类型属性
//表达式有两个属性
//1.值属性:即表达式最后的计算结果
//2.类型属性:即表达式计算结果的类型
int a = 7;
short s = 4;
printf("%d\n", sizeof(s = a + 2));//short 2
printf("%d\n", s);//4
return 0;
}