1.数组笔试题
之前,我们已经了解了数组名的意义,这里不再继续阐述。
//二维数组 //在内存中也是连续存放,二维数组是一维数组的数组 int a[3][4] = { 0 }; printf("%zd\n", sizeof(a)); //a表示整个数组,计算的是整个数组的大小,单位是字节---48字节==12个元素*每个元素的大小4字节 printf("%zd\n", sizeof(a[0][0])); //表示数组的第一行第一个元素的大小,4个字节 printf("%zd\n", sizeof(a[0])); //二维数组的数组名是a,第一行的数组名是a[0],第二行的数组名是a[1],第三行的数组名是a[2] //所以a[0]作为第一行的数组名,单独放在sizeof内部,计算的就是整个第一行的大小 //所以是16个字节 printf("%zd\n", sizeof(a[0] + 1)); //a[0]并非单独放在sizeof内部,也没有&,所以a[0]表示首元素的地址,也就是第一行第一个元素的地址 //a[0]===&a[0][0] //a[0]+1==&a[0][1] //是地址就是4/8个字节 printf("%zd\n", sizeof(*(a[0] + 1))); //a[0]+1是第一行第二个元素的地址,解引用就是第一行第二个元素,大小就是4个字节 printf("%zd\n", sizeof(a + 1)); //a作为二维数组的数组名,并没有单独放在sizeof内部,也没有&,表示的是数组首元素的地址(第一行的地址),+1就是第二行的地址,是地址就是4/8个字节,a的类型是 int(*)[4] printf("%zd\n", sizeof(*(a + 1))); //a+1是二维数组第二行的地址,解引用计算的是第二行数组的大小,就是16个字节 printf("%zd\n", sizeof(&a[0] + 1)); //a[0]是第一行的数组名,取出的是第一行的地址,+1就是第二行的地址,是地址就是4/8个字节 printf("%zd\n", sizeof(*(&a[0] + 1))); //计算的是第二行整个数组的地址,解引用访问的是第二行,计算的大小就是16个字节 printf("%zd\n", sizeof(*a)); //a表示数组首元素的地址,就是第一行的地址,*a就是第一行,解引用计算的就是第一行的大小,就是16个字节 printf("%zd\n", sizeof(a[3])); //不会越界,sizeof不会真的去访问大小,是根据类型去计算的大小,所以大小是16字节
2.指针笔试题
2.1
int main() { int a[5] = { 1, 2, 3, 4, 5 }; int *ptr = (int *)(&a + 1); printf( "%d,%d", *(a + 1), *(ptr - 1)); return 0; } //程序的结果是什么?
所以结果是 2 5.。
2.2
//结构体的大小是20个字节(x86环境) struct Test { int Num; char *pcName; short sDate; char cha[2]; short sBa[4]; }*p; //假设p 的值为0x100000。 如下表表达式的值分别为多少? //已知,结构体Test类型的变量大小是20个字节 int main() { p=(struct Test*)0x100000; printf("%p\n", p + 0x1); printf("%p\n", (unsigned long)p + 0x1); printf("%p\n", (unsigned int*)p + 0x1); return 0; }
printf("%p\n", p + 0x1);
结构体指针+1,跳过一个结构体的大小(20字节),所以p+0x1结果就是0x100014。
printf("%p\n", (unsigned long)p + 0x1);
把p强制转换成无符号整型,把指针强制转换成整型,+0x1结果就是0x100001。
printf("%p\n", (unsigned int*)p + 0x1);
把p强制转换成无符号整型指针,+1跳过4个字节,所以结果就是0x100004。
2.3
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); return 0; }
int *ptr1 = (int *)(&a + 1);
int *ptr2 = (int *)((int)a + 1);
a是首元素地址,被强制转换成int,假设a的地址是0x0012FF40,+1就是0x0012FF41,然后又被强制转换成int*指针赋值给ptr2,此时ptr2指向的就是内存中存放1的第二个字节,见下图。