#include<stdio.h>
#include<string.h>
//以下几点是需要注意的:
//sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小(只限括号内放一个单独数组名)
//&数组名,这里的数组名也表示整个数组,取出的是整个数组的地址
// 除了以上两种情况外,数组名都表示首元素的地址
//对于二维数组,首元素这个概念,要把二维数组看成一维数组,表示的是第一行的地址
//地址的大小,在32位平台上大小为4,64位平台上大小为8
// sizeof()括号内的表达式并不会参与计算,所以当出现数组访问越界时并不会报错
//占字节大小:char--1; int--4; float--4; double--8; short--2; long--4; long long--8;
//strlen()遇到'\0'才会终止计算,但'\0'不计入大小
//strlen()参数为地址(或指针),将依此作为内存起始位置开始扫描, 直到碰到第一个字符串结束符’\0’为止,然后返回计数器值
//sizeof()计算的是所占内存的大小,因此'\0'是计入大小的
//取地址操作符和解引用操作符的优先级都是大于算术操作符的
int main(){
int a[]={1,2,3,4};
char arr[]={'a','b','c','d','e','f'};
char arr2[]={"abcdef"};
char* p="abcdef";
int a2[3][4]={0};
//一维整型数组--sizeof()
printf("%d\n",sizeof(a));//a单独放在sizeof括号内,在这里求的是整个数组的大小,单位是字节--4*4==16
printf("%d\n",sizeof(a+0));//a不是单独放在括号内,则在这里表示首元素的地址--4/8
printf("%d\n",sizeof(*a));//a不是单独放在括号内,则a为首元素地址,对地址*,即解引用,*a为首元素,大小为4
printf("%d\n",sizeof(a+1));//a表示首元素地址,a+1为第二个元素地址--4/8
printf("%d\n",sizeof(a[1]));//a[1]即数组的第二个元素,大小为4
printf("%d\n",sizeof(&a));//&a取出的是整个数组的地址,仍是地址,大小--4/8
printf("%d\n",sizeof(*&a));//&a取出整个数组的地址,*对其解引用,则*&a表示整个数组的元素,其大小为4*4==16
printf("%d\n",sizeof(&a+1));//&a取出整个数组的地址,+1跳过一个数组的地址,但也仍然是地址,大小为--4/8
printf("%d\n",sizeof(&a[0]));//取出第一个元素的地址--4/8
printf("%d\n",sizeof(&a[0]+1));//取出第二个元素的地址--4/8
//一维字符数组--sizeof()
printf("%d\n",sizeof(arr)); //计算的是整个数组的大小,单位为字节--6*1==6
printf("%d\n",sizeof(arr+0));//首元素地址--4/8
printf("%d\n",sizeof(*arr)); // 对首元素地址解引用,为首元素--1
printf("%d\n",sizeof(arr[1]));//首元素--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()
printf("%d\n",strlen(arr)); //在这里计算的是整个数组的长度,但由于无'\0',不清楚在此后什么位置停止计算,所以为--随机值
printf("%d\n",strlen(arr+0)); //从首元素开始计算,同理无'\0',则--随机值
printf("%d\n",strlen(*arr)); //*arr为第一个元素,应该传入地址,用法错误,将会报错
printf("%d\n",strlen(arr[1])); //同理,报错
printf("%d\n",strlen(&arr)); //和传入arr效果一样--随机值
printf("%d\n",strlen(&arr+1)); //跳过这个数组后作为起始位置向后扫描,直到遇见'\0',为随机值,但比传入&arr小6
printf("%d\n",strlen(&arr[0]+1)); //从第二个元素开始扫描,为随机值,但比传入&arr小1
//字符串数组--sizeof()
printf("%d\n",sizeof(arr2)); //计算数组大小--7
printf("%d\n",sizeof(arr2+0)); //计算首元素地址的大小--4/8
printf("%d\n",sizeof(*arr2)); //首元素大小--1
printf("%d\n",sizeof(arr2[1])); //第二个元素大小--1
printf("%d\n",sizeof(&arr2)); //传入的是整个数组的地址--4/8
printf("%d\n",sizeof(&arr2+1)); //跳过当前数组之后的地址--4/8
printf("%d\n",sizeof(&arr2[0]+1)); //第二个元素的地址--4/8
//字符串数组--strlen()
printf("%d\n",strlen(arr2)); //计算从头开始字符串长度(字符串末尾默认有'\0')--6
printf("%d\n",strlen(arr2+0)); //同理--6
printf("%d\n",strlen(*arr2)); //对首元素地址解引用,即为首元素,用法错误,将报错
printf("%d\n",strlen(arr2[1])); //同理,报错
printf("%d\n",strlen(&arr2)); //和传入arr2一样--6
printf("%d\n",strlen(&arr2+1)); //跳过该数组之后开始扫描,直到遇见'\0'--随机值
printf("%d\n",strlen(&arr2[0]+1)); //从第二个元素开始扫描--5
//字符指针--sizeof()
printf("%d\n",sizeof(p)); //传入的是指针(首元素地址)--4/8
printf("%d\n",sizeof(p+1));//第二个元素地址--4/8
printf("%d\n",sizeof(*p)); //解引用,得到第一个元素--1
printf("%d\n",sizeof(p[0])); //第一个元素--1
printf("%d\n",sizeof(&p)); //地址--4/8
printf("%d\n",sizeof(&p+1)); //地址--4/8
printf("%d\n",sizeof(&p[0]+1)); //地址--4/8
//字符指针--strlen()
printf("%d\n",strlen(p));// 6
printf("%d\n",strlen(p+1));// 5
printf("%d\n",strlen(*p));// 用法错误,报错
printf("%d\n",strlen(p[0]);// 同理,报错
printf("%d\n",strlen(&p));// p是指向字符串的,p中存放的是该字符串中首元素的地址,而&p取的是p的地址,'\0'的存在状态未知--随机值
printf("%d\n",strlen(&p+1));// 同理--随机值
printf("%d\n",strlen(&p[0]+1);// p[0]为第一个元素,&p[0]取出第一个元素地址,+1则第二个元素地址,以此为起始位置扫描--5
//二维数组--sizeof()
printf("%d\n",sizeof(a2));// 3*4*4==48
printf("%d\n",sizeof(a2[0][0]));// 4
printf("%d\n",sizeof(a2[0]));// a2[0]指第一行--4*4==16
printf("%d\n",sizeof(a2[0]+1));// a2[0]指第一行,+1后为第一行第二个元素--4
printf("%d\n",sizeof(*(a2[0]+1));// 第一行第二个元素的地址--4/8
printf("%d\n",sizeof(a2+1));// a2并不是单独存放在括号内,则表示首元素地址,而在二维数组中,首元素地址指第一行,此处+1则为第二行地址--4/8
printf("%d\n",sizeof(*(a2+1));// 第二行地址解引用,计算第二行大小--4*4==16
printf("%d\n",sizeof(&a2[0]+1));// 第二行地址--4/8
printf("%d\n",sizeof(*a2));// 首元素地址(第一行地址)--4/8
printf("%d\n",sizeof(a2[3]));// 计算数组第四行大小,但该数组并没有第四行,所以越界了,但sizeof不会对括号内的表达式进行运算分析,因此不会报错,会按照定义中,该数组每行有四个元素进行大小返回--4*4==16
}