数组和指针
数组 - 能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型
指针 - 地址/指针变量,大小是4/8个字节
数组是数组,指针是指针,二者不等价
数组名是元素首地址,可以存放在指针变量中
就可以使用指针来遍历数组
数组名
大部分情况下是首元素地址
两个例外
sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小
&数组名,数组名表示整个数组,取出的是数组的地址
//int main()
//{
// int a[] = { 1,2,3,4 };
// printf("%d\n", sizeof(a));//16 4x4
// //sizeof(a)就是数组名单独放在sizeof内部,计算的数组总大小,单位是字节
// printf("%d\n", sizeof(a + 0));// 4/8
// //a+0不是单独将数组名放到sizeof内部,所以表示首元素地址
// //所以是4/8个字节
// printf("%d\n", sizeof(*a));// 4
// //a是数组首元素地址 - &a[0]
// //*a(解引用) -> *&a[0] -> a[0],这里是一个整型元素的大小,不是地址大小
// printf("%d\n", sizeof(a + 1));// 4/8
// //a是数组首元素地址 -- int*
// //a+1 跳过一个元素,是第二个元素的地址
// printf("%d\n", sizeof(a[1]));// 4
// //第二个元素
// printf("%d\n", sizeof(&a));// 4/8
// //&a - 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4/8个字节
// //int (*pa)[4] = &a
// printf("%d\n", sizeof(*&a));// 16
// //sizeof(a)
// //int(*)[4] 数组的指针类型
// printf("%d\n", sizeof(&a + 1));// 4/8
// //&a --> int(*)[4]
// //&a+1 跳过一个数组
// printf("%d\n", sizeof(&a[0]));// 4/8
// //取出首元素的地址
// printf("%d\n", sizeof(&a[0] + 1));//4/8
// //取出第二个元素的地址
// return 0;
//}
//sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么
//sizeof不是函数,是操作符
//strlen是函数
//strlen是针对字符串的,求的是字符串的长度,其实本质上统计的是'\0'之前出现的字符个数
//int main()
//{
// char arr[] = { 'a','b','c','d','e','f' };
// printf("%d\n", sizeof(arr));// 6
// printf("%d\n", sizeof(arr + 0));// arr+0是数组首元素的地址 4/8
// printf("%d\n", sizeof(*arr));//*arr是首元素,计算的是首元素的大小 1
// printf("%d\n", sizeof(arr[1]));// 1
// printf("%d\n", sizeof(&arr));// &arr是数组的地址 4/8
// printf("%d\n", sizeof(&arr + 1));//&arr+1跳过一个数组过后的地址 4/8
// printf("%d\n", sizeof(&arr[0] + 1));// 4 / 8
// printf("%d\n", strlen(arr));//随机值 因为不知道\0的位置
// printf("%d\n", strlen(arr + 0));//随机值
// printf("%d\n", strlen(*arr));//这里是地址,传进去的是'a' --> 97,将97作为地址编号查找,形成非法访问
// printf("%d\n", strlen(arr[1]));// 'b'--> 98 非法访问
// printf("%d\n", strlen(&arr));//随机值
// printf("%d\n", strlen(&arr + 1));//随机值-6 比上一个少6
// printf("%d\n", strlen(&arr[0] + 1));//随机值-1
// return 0;
//}
//int main()
//{
// char arr[] = "abcdef";//[a b c d e f \0]
// printf("%d\n", sizeof(arr));// 7
// printf("%d\n", sizeof(arr + 0));// 4/8
// printf("%d\n", sizeof(*arr));// *arr - 是数组首元素 1
// //arr[0] *(arr+0)
// //int sz = sizeof(arr)/sizeof(*arr)
// //int sz=sizeof(arr)/sizeof(arr[0])
// printf("%d\n", sizeof(arr[1]));//1
// printf("%d\n", sizeof(&arr));//数组的地址,4
// printf("%d\n", sizeof(&arr + 1));// 4/8
// printf("%d\n", sizeof(&arr[0] + 1));// 4/8
//
// printf("%d\n", strlen(arr));//6
// printf("%d\n", strlen(arr + 0));//6
// printf("%d\n", strlen(*arr));//error 非法访问
// printf("%d\n", strlen(arr[1]));//error 非法访问
// printf("%d\n", strlen(&arr));//6
// //&arr - char(*)[7] 与strlen的类型不同
// printf("%d\n", strlen(&arr + 1));//随机值
// printf("%d\n", strlen(&arr[0] + 1));//5
// return 0;
//}
//int main()
//{
// char* p = "abcdef";//可以想象成数组
// printf("%d\n", sizeof(p));// 4/8 计算的是指针变量的大小
// printf("%d\n", sizeof(p + 1));//'b' 的地址 4/8
// printf("%d\n", sizeof(*p));// 1
// printf("%d\n", sizeof(p[0]));//等价于*(p+0)--'a' 1
// printf("%d\n", sizeof(&p));// 4/8 是p变量的地址
// printf("%d\n", sizeof(&p + 1));// 4/8 p-- char* &p -- char**
// printf("%d\n", sizeof(&p[0] + 1));//b的地址 4/8
// 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的地址,随机值
// printf("%d\n", strlen(&p + 1));//随机值
// printf("%d\n", strlen(&p[0] + 1));// 5
// return 0;
//}
//int main()
//{
// int a[3][4] = { 0 };//可当成三个一维数组,数组名为a[0],a[1]...
// printf("%d\n", sizeof(a));// 48 4x3x4 这个二维数组的数组名单独放在sizeof内部,计算整个数组的大小
// printf("%d\n", sizeof(a[0][0]));//第一行第一个元素 4个字节
// printf("%d\n", sizeof(a[0]));// 16 4x4
// //a[0]第一行的数组名,这时数组名单独放在sizeof内部了,计算的是数组的大小,单位是字节
// printf("%d\n", sizeof(a[0] + 1));//
// //a[0]不是单独放在sizeof内部,a[0]表示首元素的地址,即第一行第一个元素的地址 - &a[0][0]
// //+1是第一行第二个元素的地址 - &a[0][1]
// printf("%d\n", sizeof(*(a[0] + 1)));//a[0][1] 大小是 4个字节
// printf("%d\n", sizeof(a + 1));//
// //a作为二维数组的数组名并非单独放在sizeof内部,所以表示首元素的地址
// //二维数组的首元素是第一行,a就是第一行的地址---int (*)[4]
// // a+1是跳过第一行,指向了第二行,是第二行的地址,数组指针
// //
// printf("%d\n", sizeof(*(a + 1)));//第二行解引用,第二行大小 4x4 16
// //*(a+1)-->a[1]
// printf("%d\n", sizeof(&a[0] + 1));//
// //&a[0]是第一行的地址
// //&a[0]+1是第二行的地址
// printf("%d\n", sizeof(*(&a[0] + 1)));// 16 等价于a[1]
// printf("%d\n", sizeof(*a));// 16 *a -- 就是第一行
// //*啊-- *(a+0) -- a[0]
// printf("%d\n", sizeof(a[3]));
// return 0;
//}
//sizeof内部不会计算,只要类型
//int main()
//{
// int a[5] = { 1, 2, 3, 4, 5 };
// int* ptr = (int*)(&a + 1);//跳过了一个数组
// printf("%d,%d", *(a + 1), *(ptr - 1));//解引用为5
// //前面是2
// return 0;
//}
//由于还没学习结构体,这里告知结构体的大小是20个字节
//struct Test
//{
// int Num;
// char* pcName;
// short sDate;
// char cha[2];
// short sBa[4];
//}*p;
假设p 的值为0x100000。 如下表表达式的值分别为多少?
已知,结构体Test类型的变量大小是20个字节
//int main()
//{
// printf("%p\n", p + 0x1);
// printf("%p\n", (unsigned long)p + 0x1);//不是指针,该加多少加多少
// printf("%p\n", (unsigned int*)p + 0x1);//指针加一
// //0x100004
// return 0;
//}
结构体20个字节,指针加一跳过20个字节变成0x100014