//
// printf(“%d\n”, sizeof(a+0));// 输出为 4 / 8
// // 因为 sizeof()的括号里放的不是数组名,而是 首元素地址 + 0,即sizeof(&a[0])
//
// printf(“%d\n”, sizeof(*a));// 4 因为 a 没有 &(取地址),没有单独放在sizeof()里
// // 这里求的是 首元素 的内存大小,*a 就是首元素
//
// printf(“%d\n”, sizeof(a+1));// 4 / 8 与a + 0 的意思是一样的,只是现在这里跳过一个元素
// // 这里是在求第二个元素的内存大小
//
// printf(“%d\n”, sizeof(a[1]));// 4
//
// printf(“%d\n”, sizeof(&a));// 4 / 8 &a 取出的是数组的地址
// // 但 数组的地址也是地址 : 32位 / 64 位
//
// printf(“%d\n”, sizeof(*&a));// 16 一个数组的地址,解引用 访问整个数组,可以说解引用和取地址相互抵消了
//
// printf(“%d\n”, sizeof(&a+1));// 4 / 8 &a,拿出的是a的地址,+1跳过整个数组,但还是一个地址
//
// printf(“%d\n”, sizeof(&a[0]));// 4 / 8 第一个元素的内存大小
// printf(“%d\n”, sizeof(&a[0]+1));// 4 / 8 第二个元素的内存大小
// return 0;
//}
// 字符数组
//#include<stdio.h>
//int main()
//{
// char arr[] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ };
// printf(“%d\n”,sizeof(arr));// 6
// printf(“%d\n”, sizeof(arr+0));//4 / 8 首元素地址+ 0,还是一个地址
// printf(“%d\n”, sizeof(*arr));// 1 *arr(对首元素地址进行解引用) == 首元素
// printf(“%d\n”, sizeof(arr[1]));// 1 第二个元素的大小
// printf(“%d\n”, sizeof(&arr));// 4 / 6 这里是一个地址
// printf(“%d\n”, sizeof(&arr+1));// 4 / 8 这里还是一个地址
// printf(“%d\n”, sizeof(&arr[0]+1));// 4 / 8 一个地址
// return 0;
//}
//#include<stdio.h>
//#include<string.h>
//int main()
//{
// char arr[] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’ };
// printf(“%d\n”, strlen(arr));// 随机值, 没有’\0’
// printf(“%d\n”, strlen(arr + 0));// 随机值
// //printf(“%d\n”, strlen(*arr));// *arr == ‘a’ == 97 strlen(把97当成一个地址),非法访问,程序崩溃
// //printf(“%d\n”, strlen(arr[1]));// 与上表达式一样, 非法访问,程序崩溃
// printf(“%d\n”, strlen(&arr));// 随机值
// printf(“%d\n”, strlen(&arr + 1));// 随机值 - 6 ,与上表示式的随机值 ,相差 6
// printf(“%d\n”, strlen(&arr[0] + 1));// 随机值 - 1,与 上上 表达式的随机值,相差 1
// return 0;
//}
//#include<stdio.h>
//#include<string.h>
//int main()
//{
// char arr[] = “abcdef”;
// printf(“%d\n”, sizeof(arr));// 7 后面隐藏一个元素 ‘\0’
// printf(“%d\n”, sizeof(arr + 0));// 4 / 8 是一个地址,
// printf(“%d\n”, sizeof(*arr));// 1 *arr == 首元素,这里计算的是首元素的内存大小
// 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, 这是一个地址
//
//
//
// printf(“%d\n”, strlen(arr));// 6 遇到’\0’停止计数,'\0’不计入在内
// printf(“%d\n”, strlen(arr + 0));// 6 从首元素开始计数,遇到’\0’停止计数,'\0’不计入在内
// printf(“%d\n”, strlen(*arr));// *arr == a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃
// printf(“%d\n”, strlen(arr[1]));// arr[1] == b == 98,以98为地址( 从 98 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃
// printf(“%d\n”, strlen(&arr));// 6 从首元素开始计数,遇到’\0’停止计数,'\0’不计入在内
// printf(“%d\n”, strlen(&arr + 1));// 随机值,跳过了一个数组,从 ‘\0’ 后面 开始计数,直到遇到’\0’停止计数,'\0’不计入在内
// printf(“%d\n”, strlen(&arr[0]) + 1);// 5 从第二个元素开始计数,遇到’\0’停止计数,'\0’不计入在内
//
// return 0;
//}
//#include<stdio.h>
//#include<string.h>
//int main()
//{
// char* p = “abcdef”;
// printf(“%d\n”, sizeof§);// 4 / 8 a 的地址
// printf(“%d\n”, sizeof(p + 0));// 4 / 8 b 的地址,
// printf(“%d\n”, sizeof(*p));// 1 *arr == 首元素 a,这里计算的是首元素的内存大小
// printf(“%d\n”, sizeof(p[0]));// 1 计算第一个元素的内存大小 p[0] == *(p+0) == a
// printf(“%d\n”, sizeof(&p));// 4 / 8 把指针变量本身的地址取出来了,是一个地址
// printf(“%d\n”, sizeof(&p + 1));// 4 / 8 地址
// printf(“%d\n”, sizeof(&p[0]) + 1);// 4 / 8, b 的地址
//
//
//
// printf(“%d\n”, strlen§);// 6 指针变量 p 存的是 a的地址,从p开始计算,直到遇到’\0’停止,'\0’不计入在内
// printf(“%d\n”, strlen(p + 1));// 5 指针变量 p 存的是 b 的地址,从p开始计算,直到遇到’\0’停止,'\0’不计入在内
// printf(“%d\n”, strlen(*p));// *p == a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃
// printf(“%d\n”, strlen(p[0]));// p[0] == a == 97,以97为地址( 从 97 开始计算直到遇到’\0’ ),属于非法访问,程序崩溃
// printf(“%d\n”, strlen(&p));// 随机值, 这里是指针变量 p 的地址,不是a的地址
// printf(“%d\n”, strlen(&p + 1));// 随机值,
// printf(“%d\n”, strlen(&p[0]) + 1);// 5 取出第一个元素的地址加一,到第 二 个元素,从第二个元素计算,直到遇到’\0’停止,'\0’不计入在内
//
// return 0;
//}
// 二维数组
//#include<stdio.h>
//#include<string.h>
//int main()
//{
// int a[3][4] = { 0 };
// printf(“%d\n”, sizeof(a));// 48 3*4*4 = 12*4 = 48
// printf(“%d\n”, sizeof(a[0][0]));// 4 第一行第一个元素
// printf(“%d\n”, sizeof(a[0]));// 16 把第0行看成一个一维数组,a[0]就是一个一维数组的数组名,所以计算的整个第 0 行元素的内存大小 4 * 4 = 16
// printf(“%d\n”, sizeof(a[0] + 1));// 4 / 8 第0行 第2个元素的地址
// printf(“%d\n”, sizeof(*(a[0] + 1)));// 4 第0行 第2个元素
//
// printf(“%d\n”, sizeof(a + 1));// 4 / 8 第1行 的 一维数组 的 地址
// printf(“%d\n”, sizeof(*(a + 1)));// 16 解引用 第一行的一维数组的数组名(首元素)的地址,等于就是找到第一行的一维数组的数组名,
// //sizeof(第一行 的 数组名 ),所以计算的是整个第一行元素的内存大小
//
// printf(“%d\n”, sizeof(&a[0] + 1));// 4 / 8 第 1 行(第一行的一维数组名)的 地址,
// printf(“%d\n”, sizeof(*(&a[0]) + 1));// 16 解引用 第 1 行(第一行的一维数组名)的 地址,等于找到了 第 1 行的一维数组的数组名
// //sizeof(第一行 的 数组名 ),所以计算的是整个第一行元素的内存大小
// printf(“%d\n”, sizeof(*a));// 16 a是首元素的地址(第 0 行的数组地址) ,*a(解引用 a )找到了第0行数组名,
// //计算的是整个第 0 行所有元素的内存大小
// printf(“%d\n”, sizeof(a[3]));//16 ,另外 sizeof()括号里表达式不会计算,也就是说不会真的访问第四行数据,它只是把第四行的数组名放在这里()
// //意思这里有第四行,就意味着 第四行 有 它自己 的 类型 ,其实这里 a[3] 跟 a[0] 一样的道理,
// //a[3] 是第四行的数组名,那有 第四行吗?其实没有,但并不妨碍,因为我们不去访问
// // 而且 sizeof() 括号里的 表达式 是不参与真是运算的 ,只是 根据 它的类型 计算 它的大小
// // 所以 a[3] 是一个一维数组,而且有 4 个整形的一维数组,sizeof(a[3]) == 4 * 4 == 16
//
// return 0;
//}
//指针题
//#include<stdio.h>
//int main()
//{
// int a[5] = { 1, 2, 3, 4, 5 };
// int* ptr = (int*)(&a + 1);// 数组的指针类型,不能放进一个整形指针里,所以这里强制类型转换,但值没有发生变换,
// // 存的值,还是跳过一个数组的指向的那个值(未知量)
// printf(“%d,%d\n”, *(a + 1), *(ptr - 1));// 整形指针 ptr 减一,指向 5 的 那个位置,再解引用就是5
// return 0; // 2 5
//}
//struct test
//{
// int num;
// char* pcname;
// short s_date;
// char cha[2];
// short s_ba[4];
//}* p;
// 假设 p 的 值为 0x10 00 00 00,如下表达式分别为多少
// 已知结构体 test 类型 的 变量 大小为 20个字节
//#include<stdio.h>
//int main()
//{
// p = (struct test*)0x100000;
// printf(“%p\n”, p + 0x1);// 0x1 == 1 这里加1 等于跳过了一个结构体(20字节)
// //0x10 00 00 + 20 ==0x10 00 14 因为 %p(32位)
// //打印 0x 00 10 00 14
//
// printf(“%p\n”, (unsigned long)p + 0x1); // 强制类型转换 无符号长整形类型,0x100000 转换为 10 进制 -> 1048576 + 1 = 1048577 -> 0x10 00 01
// // %p, 即0x 00 10 00 01
//
// printf(“%p\n”, (unsigned int*)p + 0x1);//强制类型转换 无符号整形指针类型 加1 == 就是跳过一个无符号整形指针(4 byte)
// // 即 0x 00 10 00 04
// return 0;
//}
//#include<stdio.h>
//int main()
//{
// int a[4] = { 1, 2, 3, 4 };
// int* ptr1 = (int*)(&a + 1);
// int* ptr2 = (int*)((int)a + 1);
// printf(“%x,%x”, ptr1[-1], *ptr2);// %x 十六进制数
// return 0; // 4 2 000 000
//}
1 2 3 4
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
低地址 高地址(小端 存储:低字节存低地址,高字节存高地址)
a 是数组名(首元素地址),指向 1 所在的地址(01前面)。这时类型强制转换 整形,加1(1字节),
再将他转换为一个地址,在对其解引用 ,此时它(ptr2)指向 01 的后面,又因为ptr2是int 类型
也就是说它一次访问 4 个字节的内容( 00 00 00 02 ) 取出来使反着读取(从高位开始读取),02 00 00 00
按十六进制 输出 (0x 02 00 00 00) 即,2 000 000
//#include<stdio.h>
//int main()
//{ // 1 3 5
// int a[3][2] = { ( 0, 1 ), ( 2, 3 ), ( 4, 5) };
// int* p; //逗号表达式,以最后一个表达式结果为准
// // 数组存储情况 1 3
// // 5 0
// // 0 0
// p = a[0];
// printf(“%d\n”,p[0]); // 1
// return 0;
//}
//#include<stdio.h>
//int main()
//{
// int a[5][5];
// // a[0] a[1] a[2] a[3] a[4]
// // 口口口口口 口口口口口 口口口口口 口口口口口 口口口口口
// // | | | | | | |
// //p[0] p[1] p[2] p[3] p[4] | a[4][2]
// // p[4][2]