本章带给大家一些指针与数组的笔试题并且附有解析
目录
数组
第一题
在64位的平台下,下面程序运行结果为:
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(a[1]));
printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));
printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));
return 0;
}
解析
1. sizeof( 数组名 ) ,这里的数组名表示整个数组,计算的是整个数组的大小。2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。3. 除此之外所有的数组名都表示首元素的地址。
int main()
{
//数组名是首元素地址(除了两种特殊情况)
//1.sizeof(数组名 )--- 数组名表示整个数组
//2.&数组名 --- 数组名表示整个数组
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//符合我们的第一种情况,数组名代表整个数组,所以大小就是4*4=16个字节
printf("%d\n", sizeof(a + 0));//此时a代表的是首元素地址,那么首元素地址+0还是首元素地址,地址占8个字节
printf("%d\n", sizeof(*a));//对首元素地址进行解引用就是数组里的1,所以占4个字节
printf("%d\n", sizeof(a + 1));//此时a代表的是首元素地址,那么首元素地址+1就是第2个元素的地址,地址占8个字节
printf("%d\n", sizeof(a[1]));//第2个元素的大小,也就是2的大小占4个字节
printf("%d\n", sizeof(&a));//符合第2种情况,a表示整个数组,&然后取整个数组的地址,地址占8个字节
printf("%d\n", sizeof(*&a));//符合第2种情况,a表示整个数组,&然后取整个数组的地址,再对其解引用就是整个数组的大小16个字节
printf("%d\n", sizeof(&a + 1));//符合第2种情况,a表示整个数组,&然后取整个数组的地址,再+1就是跳过数组之后的地址占8个字节
printf("%d\n", sizeof(&a[0]));//第一个元素的地址占8个字节
printf("%d\n", sizeof(&a[0] + 1));//第2个元素的地址占8个字节
return 0;
}
运行结果
第二题
在64位的平台下,下面程序运行结果为:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
return 0;
}
解析
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//整个数组的大小6*1=6个字节
printf("%d\n", sizeof(arr + 0));//首元素地址的大小,占8个字节
printf("%d\n", sizeof(*arr));//对首元素的地址解引用就是a的大小为1个字节
printf("%d\n", sizeof(arr[1]));//第二个元素的大小为1个字节
printf("%d\n", sizeof(&arr));//整个数组的地址占8个字节
printf("%d\n", sizeof(&arr + 1));//跳过整个数组后的地址,占8个字节
printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,占8个字节
return 0;
}
运行结果
第三题
在64位的平台下,下面程序运行结果为:
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
解析
int main()
{
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//传进来的是arr的首地址,向后搜索一直搜索到‘\0’位置,所以是个随机值
printf("%d\n", strlen(arr + 0));//随机值
printf("%d\n", strlen(*arr));//传进来的是字符‘a’而不是地址,此时相当于非法访问97的地址
printf("%d\n", strlen(arr[1]));//同理非法访问
printf("%d\n", strlen(&arr));//整个数组的地址,答案也是随机值
printf("%d\n", strlen(&arr + 1));//从整个数组之后开始搜索‘\0’,答案是随机值-6
printf("%d\n", strlen(&arr[0] + 1));//从第2个位置开始向后搜索‘\0’,结果为随机值-1
return 0;
}
运行结果
第四题
在64位的平台下,下面程序运行结果为:
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr + 0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr + 1));
printf("%d\n", strlen(&arr[0] + 1));
return 0;
}
解析
int main()
{
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//整个数组的大小包含‘\0’7*1=7个字节
printf("%d\n", sizeof(arr + 0));//计算的是首地址的大小也就是8个字节
printf("%d\n", sizeof(*arr));//计算的是第1个元素的大小也就是1个字节
printf("%d\n", sizeof(arr[1]));//第2个元素的大小也就是1个字节
printf("%d\n", sizeof(&arr));//整个数组的地址也就是8个字节
printf("%d\n", sizeof(&arr + 1));//跳过数组之后的地址,8个字节
printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,8个字节
printf("\n");
printf("%d\n", strlen(arr));//传入数组首地址向后找‘\0’,结果为6
printf("%d\n", strlen(arr + 0));//传入数组首地址+1向后找‘\0’,结果为6
//printf("%d\n", strlen(*arr));//传入的是字符a相当于地址97,会显示非法访问
//printf("%d\n", strlen(arr[1]));//传入的是第二个元素字符b相当于地址98,会显示非法访问
printf("%d\n", strlen(&arr));//整个数组的地址,结果为6
printf("%d\n", strlen(&arr + 1));//跳过整个数组之后的地址,结果为一个随机值
printf("%d\n", strlen(&arr[0] + 1));//从第二个元素后面开始找‘\0’,结果为5
return 0;
}
运行结果
第五题
在64位的平台下,下面程序运行结果为:
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a[0][0]));
printf("%d\n", sizeof(a[0]));
printf("%d\n", sizeof(a[0] + 1));
printf("%d\n", sizeof(*(a[0] + 1)));
printf("%d\n", sizeof(a + 1));
printf("%d\n", sizeof(*(a + 1)));
printf("%d\n", sizeof(&a[0] + 1));
printf("%d\n", sizeof(*(&a[0] + 1)));
printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[3]));
return 0;
}
解析
int main()
{
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//此时计算整个数组的大小也就是3*4*4=48个字节
printf("%d\n", sizeof(a[0][0]));//第一行第一个元素的大小4个字节
printf("%d\n", sizeof(a[0]));//a[0]表示第一行的地址,第一行元素的大小4*4=16个字节
printf("%d\n", sizeof(a[0] + 1));//a[0]在此时表示第一行的首地址,计算第一行第二个元素的地址占8个字节
printf("%d\n", sizeof(*(a[0] + 1)));//第一行第二个元素的大小4个字节
printf("%d\n", sizeof(a + 1));//a表示第一行的地址,此时计算第二行的地址占8个字节
printf("%d\n", sizeof(*(a + 1)));//第二行的大小占4*4=16个字节
printf("%d\n", sizeof(&a[0] + 1));//第二行的地址占8个字节
printf("%d\n", sizeof(*(&a[0] + 1)));//第二行的大小占4*4=16个字节
printf("%d\n", sizeof(*a));//第一行元素的地址然后解引用就是第一行的大小4*4=16个字节
printf("%d\n", sizeof(a[3]));//只是一个数组名sizeof里面的表达式不计算所以也是16个字节
return 0;
}
运行结果
指针
第一题
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
解析
ptr是一个指针指向的是数组a后面的地址,ptr-1就是数组a最后一个元素的地址,解引用就是5,a+1是第二个元素的地址,解引用就是2.
运行结果
第二题
32位平台下程序的结果是什么?
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
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;
}
解析
结构体的大小是20个字节,第一个p+1,p是结构体指针类型,结构体大小是20个字节,所以+1就跳过20个字节再转换为16进制就是00100014。
第二个强制转换为一个无符号的长整型,+1之后就是00100001。
第三个强制转换为无符号整型指针,+1就向后跳过4个字节结果就为00100004
运行结果
第三题
在32为平台下下面程序的运行结果为
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;
}
解析
ptr1是一个指针,&a为整个数组的地址,+1就是跳过整个数组之后的首地址,ptr1[-1]等同于
*(ptr1-1)也就是数组中最后一个元素的地址。所以ptr[-1]的值就是2。
(int)a + 1就相当于把地址给+1了此时就是01后面的地址,
如图,存进去就是02000000.
运行结果
第四题
在32为平台下下面程序的运行结果为
int main()
{
int a[5][5];
int(*p)[4];
p = a;
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
解析
p的类型是int(*)[4]而a要传的是int(*)[5],这就使得
p每加一只能拿4个字节使得p[4][2]的地址比a[4][2]少4个,以十进制整型输出就是-4,以16进制输出,-4的16进制结果是FFFFFFFC
运行结果
第五题
在32为平台下下面程序的运行结果为
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));
return 0; }
解析
aa数组第一行存放的是1,2,3,4,5第二行存放的是6,7,8,9,10。&aa+1是整个数组之后的首地址,(aa+1)是a[1]的地址,所以*(ptr1 - 1)的结果是10,*(ptr2 - 1)的结果是5.
运行
第六题
在32为平台下下面程序的运行结果为
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *a);
printf("%s\n", *pa);
return 0;
}
解析
a是一个指针数组,里面分别存放work,at,alibaba,的首地址,pa是一个指针,类型是char*,pa++就是指向at的首地址,解引用之后就是at
运行结果
第七题
计算下面程序的运行结果
int main()
{
char* c[] = { "ENTER","NEW","POINT","FIRST" };
char** cp[] = { c + 3,c + 2,c + 1,c };
char*** cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
解析
int main()
{
char* c[] = { "ENTER","NEW","POINT","FIRST" };//E,N,P,F
char** cp[] = { c + 3,c + 2,c + 1,c };//F,P,N,E
char*** cpp = cp;//F
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
return 0;
}
c是一个数组里面放着E,N,P,F的地址,cp也是一个数组F,P,N,E地址的地址,cpp放着F地址的地址的地址。
1.++cpp为P的地址的地址的地址,两次解引用就是p向后找\0,输出结果为POINT
2.++cpp为N的地址的地址的地址,解引用就是N的地址的地址,--之后就是E的地址的地址,然后再解引用就是E的地址,+3之后就是E的地址向后搜索\0就是ER
3.cpp[-2]=*(cpp-2)得到F的地址的地址*之后得到F的地址+3得到S的地址输出ST
4.cpp[-1][-1]=*(*(cpp-1)-1)得到的是N的地址+1就是E的地址输出EW