这里列举了一些关于一维数组、二维数组、字符数组、指针、多级指针方面的辨析和笔试题,可复制代码后取消注释编译运行,如有问题或不解处欢迎大家交流。
Tips:
数组名的意义:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
//int main()
//{
//一维数组
// int a[] = { 1,2,3,4 };
// printf("%d\n", sizeof(a)); //16 此处代表整个数组大小
// printf("%d\n", sizeof(a + 0)); //4/8 首元素地址的大小
// printf("%d\n", sizeof(*a)); //4 首元素大小int型,4字节
// printf("%d\n", sizeof(a + 1)); //4/8 首元素地址为int*,+1后跳过4字节,为第二个元素地址大小
// printf("%d\n", sizeof(a[1])); //4 第二个元素大小int型,4字节
// printf("%d\n", sizeof(&a)); //4/8 &a虽然是数组的地址,sizeof计算的依然是一个地址的大小
// printf("%d\n", sizeof(*&a)); //16 *&抵消,仍是数组的大小
// printf("%d\n", sizeof(&a + 1)); //4/8 跳过整个数组后的地址
// printf("%d\n", sizeof(&a[0])); //4/8 首元素地址的大小
// printf("%d\n", sizeof(&a[0] + 1)); //4/8 第二个元素地址大小
//字符数组
// char arr[] = { 'a','b','c','d','e','f' };
// printf("%d\n", sizeof(arr)); //6 数组中未存放'\0'
// printf("%d\n", sizeof(arr + 0)); //4/8 首元素地址大小
// printf("%d\n", sizeof(*arr)); //1 首元素大小,char占1字节
// printf("%d\n", sizeof(arr[1])); //1 第二个元素大小,char占1字节
// printf("%d\n", sizeof(&arr)); //4/8 数组地址
// printf("%d\n", sizeof(&arr + 1)); //4/8 跳过整个数组后的地址,若+2则跳过12字节
// printf("%d\n", sizeof(&arr[0] + 1)); //4/8 第二个元素地址大小
//int mystrlen(char* str)
// {
// char* end = &str[0], * start = &str[0];
// while (*end != '\0')
// {
// end++;
// }
// return end - start;
// }
// char arr[] = { 'a','b','c','d','e','f' };
// printf("%d\n", strlen(arr)); //随机 从首元素地址出发找'\0'
// printf("%d\n", strlen(arr + 0)); //随机 从首元素地址出发找'\0'
// printf("%d\n", strlen(*arr)); //err 将a-97当作地址传参出现错误
// printf("%d\n", strlen(arr[1])); //err 将b-98当作地址传参出现错误
// printf("%d\n", strlen(&arr)); //随机 取出数组地址,类型为char(*)[6],传参后类型变为char*
// printf("%d\n", strlen(&arr + 1)); //随机 取出跳过整个数组后的地址,是上一个随机值-6
// printf("%d\n", strlen(&arr[0] + 1)); //随机 从第二个元素地址出发找'\0',是第一个随机值-1
// char arr[] = "abcdef";
// printf("%d\n", sizeof(arr)); //7
// 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 第二个元素地址大小
// char arr[] = "abcdef";
// printf("%d\n", strlen(arr)); //6
// printf("%d\n", strlen(arr + 0)); //6
// printf("%d\n", strlen(*arr)); //err 将a-97当作地址传参出现错误
// printf("%d\n", strlen(arr[1])); //err 将b-98当作地址传参出现错误
// printf("%d\n", strlen(&arr)); //6 取出数组地址,仍然从a出发找'\0'
// printf("%d\n", strlen(&arr + 1)); //随机
// printf("%d\n", strlen(&arr[0] + 1)); //5 从第二个元素b地址出发找'\0'
// char* p = "abcdef"; //p中存放的是a的地址
// printf("%d\n", sizeof(p)); //4/8 a的地址大小
// printf("%d\n", sizeof(p + 1)); //4/8 b的地址大小
// printf("%d\n", sizeof(*p)); //1 a的大小,类型为char
// printf("%d\n", sizeof(p[0])); //1 p[0]<=>*(p+0)<=>*p,同上
// printf("%d\n", sizeof(&p)); //4/8 变量p的地址的大小
// printf("%d\n", sizeof(&p + 1)); //4/8 跳过p后的地址的大小
// printf("%d\n", sizeof(&p[0] + 1)); //4/8 b的地址大小
// char* p = "abcdef";
// printf("%d\n", strlen(p)); //6 从首元素a地址出发找'\0'
// printf("%d\n", strlen(p + 1)); //5 从第二个元素b地址出发找'\0'
// printf("%d\n", strlen(*p)); //err p中存放的是a的地址,解引用即为a,将a-97当作地址传参出现错误
// printf("%d\n", strlen(p[0])); //err p[0]<=>*(p+0)<=>*p,同上
// printf("%d\n", strlen(&p)); //随机 从变量p地址出发找'\0'
// printf("%d\n", strlen(&p + 1)); //随机 从跳过p后的地址出发找'\0'(同上无关,因为p的4个字节中是否有'\0'未知)
// printf("%d\n", strlen(&p[0] + 1)); //5 从第二个元素b地址出发找'\0'
//二维数组
// int a[3][4] = { 0 };
// printf("%d\n", sizeof(a)); //48 3*4*sizeof(int)
// printf("%d\n", sizeof(a[0][0])); //4 第一行第一个元素大小
// printf("%d\n", sizeof(a[0])); //16 a[0]可理解为第一行的数组名,单独放在sizeof内部计算的是整个第一行的大小
// printf("%d\n", sizeof(a[0] + 1)); //4/8 此处a[0]指第一行的首元素地址,+1为第一行第二个元素的地址
// printf("%d\n", sizeof(*(a[0] + 1))); //4 第一行第二个元素的大小,类型为int
// printf("%d\n", sizeof(a + 1)); //4/8 a是二维数组首元素地址,即第一行元素的地址,+1为第二行元素的地址
// printf("%d\n", sizeof(*(a + 1))); //16 *(a+1)<=>a[1],第二行元素的大小
// printf("%d\n", sizeof(&a[0] + 1)); //4/8 &a[0]取出第一行的地址,+1为第二行元素的地址
// printf("%d\n", sizeof(*(&a[0] + 1))); //16 第二行元素的大小
// printf("%d\n", sizeof(*a)); //16 a是第一行元素的地址,解引用后为第一行元素的大小
// printf("%d\n", sizeof(a[3])); //16 sizeof()内部的表达式不计算!类型为int[4],即使不存在仍可通过类型得结果
// return 0;
//}
以下是部分笔试题及解析:
Tips:
%d 有符号10进制整数
%i 有符号10进制整数
%o 无符号8进制整数
%u 无符号10进制整数
%x 无符号的16进制数字,并以小写abcdef表示
%X 无符号的16进制数字,并以大写ABCDEF表示
%F/f 浮点数
%E/e 用科学表示格式的浮点数
%g 使用%f和%e表示中的总的位数表示最短的来表示浮点数 G 同g格式,但表示为指数
%c 单个字符
%s 字符串
//int main()
//{
// int a[4] = { 1, 2, 3, 4 };
// int* ptr1 = (int*)(&a + 1);
// int* ptr2 = (int*)((int)a + 1);//a为首元素地址,地址+1是+1字节!!!
// printf("%x,%x", ptr1[-1], *ptr2);//ptr1[-1]<=>*(ptr1-1),整型指针-1解引用后向前跳4字节
// //*ptr2 整型指针解引用向后访问4字节
// return 0;
// //小端存储:|01 00 00 00 |02 00 00 00 |03 00 00 00 |04 00 00 00|
// // &a |00 00 00 02| | &a+1
// // (int)a + 1 ptr1-1 ptr1
// //读取: *ptr2:0x02000000 *(ptr1-1):0x00000004
// //输出结果:4,2000000 (%x 无符号的16进制数字,并以小写abcdef表示,打印有效数字)
//}
//int main()
//{
// int a[3][2] = { (0, 1), (2, 3), (4, 5) };//逗号表达式!!!其结果为最后一项,如(0,1)结果为1
// int* p; //1 3
// p = a[0]; //5 0
// printf("%d", p[0]); //0 0 最终:p[0]为1
// return 0;
//}
//int main()
//{
// int a[5][5];
// int(*p)[4];
// p = a; //a是首元素地址int(*)[5],p是int(*)[4],存在类型差异
// printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
// //|0 0 0 0|0 低地址-高地址=-4
// // 0 0 0|0 0 原码 10000000 00000000 00000000 00000100 %d有符号数打印-4
// // 0 0|0 0 0 反码 11111111 11111111 11111111 11111011
// // 0|0 0(0)0 p[4][2] 补码 11111111 11111111 11111111 11111100 %p为地址,无符号
// // 0 0(0)0 0 a[4][2] F F F F F F F C %p将补码直接解析成原码,并以十六进制打印
// return 0;
//}
//int main()
//{
// int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// int* ptr1 = (int*)(&aa + 1);
// int* ptr2 = (int*)(*(aa + 1));
// printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//10,5
// return 0;
//}
//int main()
//{
// char* a[] = { "work","at","alibaba" };
// char** pa = a;
// pa++;
// printf("%s\n", *pa);//at
// return 0;
//}
//***重点题型***
//int main()
//{
// char* c[] = { "ENTER","NEW","POINT","FIRST" };
// char** cp[] = { c + 3,c + 2,c + 1,c };
// char*** cpp = cp;
// printf("%s\n", **++cpp); //POINT
// printf("%s\n", *-- * ++cpp + 3); //ER
// printf("%s\n", *cpp[-2] + 3); //ST
// printf("%s\n", cpp[-1][-1] + 1); //EW
// //画图分析
// //注意:1.++cpp一次cpp已被更改 2.++优先级高于+ 3.cpp[-1][-1]<=>*(*(cpp-1)+1)
// return 0;
//}
最后一题画图分析可解。