• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

指针与数组笔试题解析

互联网 diligentman 4天前 3次浏览

指针与数组笔试题解析

一维数组

int main()
{
	int a[]={1,2,3,4};
	printf("%dn",sizeof(a));//16
    printf("%dn",sizeof(a+0));//16(第一次的答案)  -4  数组名这里表示首元素地址,a+0还是首元素地址
    printf("%dn",sizeof(*a));//4
	printf("%dn",sizeof(a+1));//4
	printf("%dn",sizeof(a[1]));//4
	printf("%dn",sizeof(&a));//16   -4  &a取出的是数组的地址,但是数组的地址也是地址,答案4
	printf("%dn",sizeof(*&a));//4   -16 &a是数组的地址,数组的地址解引用访问的数组,sizeof计算就是数组的大小
	printf("%dn",sizeof(&a+1));//1   -4  &a+1也是一个地址,跳过了一个数组。
	printf("%dn",sizeof(&a[0]));//4
	printf("%dn",sizeof(&a[0]+1));//4
	return 0;
}

字符串

int main()
{
	char arr[]={'a','b','c','d','e','f'};
	printf("%dn",sizeof(arr));//7    -6//sizeof计算的是数组大小,6*1=6字节
	printf("%dn",sizeof(arr+0));//1   -4//首元素地址
	printf("%dn",sizeof(*arr));//1     
	printf("%dn",sizeof(arr[1]));//1
	printf("%dn",sizeof(&arr));//4
	printf("%dn",sizeof(&arr+1));//4
	printf("%dn",sizeof(&arr[0]+1));//4
	
	printf("%dn",strlen(arr));//6    //随机值,stelen需要遇到才停止计数
    printf("%dn",strlen(arr+0));//1   //随机值
	//printf("%dn",strlen(*arr));//err  strlen(地址) *arr 首元素'a' a的ASCII的值为97,strlen就会将97作为地址,进行访问,此时已经非法访问了
	//printf("%dn",strlen(arr[1]));//err
	//printf("%dn",strlen(&arr));// 随机值
	//printf("%dn",strlen(&arr+1));// 随机值-6
	printf("%dn",strlen(&arr[0]+1));//1  //随机值-1
	return 0;
}
int main()
{
	char arr[]="abcdef";
	printf("%dn",sizeof(arr));//6    -7   sizeof计算的数组大小,单位是字节:7
	printf("%dn",sizeof(arr+0));//4     计算是地址的大小-arr,0是首元素地址
	printf("%dn",sizeof(*arr));//1       *arr是首元素,sizeof(*arr)计算首元素的大小
	printf("%dn",sizeof(arr[1]));//1     arr[1]是第二个元素,sizeof(arr[1])计算第二个元素的大小
	printf("%dn",sizeof(&arr));//4       &arr虽然是数组的地址,但也是地址,大小是4/8字节
	printf("%dn",sizeof(&arr+1));//4     &arr+1是跳过整个数组的地址,但也是地址
	printf("%dn",sizeof(&arr[0]+1));//4  &arr[0]+1是第二个元素的地址
     
    printf("%dn",strlen(arr));//6
    printf("%dn",strlen(arr+0));//6
	//printf("%dn",strlen(*arr));//err
	//printf("%dn",strlen(arr[1]));//err
	//printf("%dn",strlen(&arr));//6    &arr 数组的地址-数组指针   char(*p)[7] =&arr;  strlen的参数是const char*
	//printf("%dn",strlen(&arr+1));//随机值
	printf("%dn",strlen(&arr[0]+1));//5
	return 0;

}

int main()
{
	char *p="abcdef";
	printf("%dn",sizeof(p));//4  计算指针变量的大小
	printf("%dn",sizeof(p+1));//4  p+1得到的字符b的地址
	printf("%dn",sizeof(*p));//1    *p就是字符串的第一个字符--a
	printf("%dn",sizeof(p[0]));//1   p[0]==*(p+0) =='a'
	printf("%dn",sizeof(&p));//4    是取出p的地址,而不是计算数组的大小
	printf("%dn",sizeof(&p+1));//4   取出跳过一个p的地址
	printf("%dn",sizeof(&p[0]+1));//4   取出b的地址

    printf("%dn",strlen(p));//6      
    printf("%dn",strlen(p+1));//5
	printf("%dn",strlen(*p));//err
	printf("%dn",strlen(p[0]));//err
	printf("%dn",strlen(&p));//随机值   取出的是p的地址,p后面位置不可知
	printf("%dn",strlen(&p+1));//随机值
	printf("%dn",strlen(&p[0]+1));//5   取出的b的地址

二维数组

int main()
{
	int a[3][4]={0};
	printf("%dn",sizeof(a));//48
	printf("%dn",sizeof(a[0][0]));//4  
	printf("%dn",sizeof(a[0]));//16
	printf("%dn",sizeof(a[0]+1));//16     -4  a[0]是第一行数组名,数组名此时代表的是首元素地址,a[0]+1 是第二个元素地址
	printf("%dn",sizeof(*(a[0]+1)));//4   
	printf("%dn",sizeof(a+1));//4   a是二维数组的数组名,没有sizeof(数组名),也没有&(数组名),所以a是首元素地址,而把二维数组看成一维数组时,二维数组的首元素就是它的第一行,a就是第一行地址,a+1就是第二行地址
	printf("%dn",sizeof(*(a+1)));//4      -16     *(a+1)就是对第二行解引用
	printf("%dn",sizeof(&a[0]+1));//4          
	printf("%dn",sizeof(*(&a[0]+1)));//4      -16  &(数组名)代表是第一行数组的地址,&a[0]+1就是第二行地址,对其解引用就是对第二行解引用
	printf("%dn",sizeof(*a));//4          -16  a是首元素地址-第一行地址,*a就是第一行
	printf("%dn",sizeof(a[3]));//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));//2,5
   return 0;
}

*(a+1),a是数组名,代表的是首元素的地址,a+1就是第二个元素的地址, * (a+1)就是第二个元素。
&a+1 ,&a是取出整个数组的地址,&a+1就是跳过一个数组,指向数组的后一个位置。ptr-1就是指向了数组最后一个元素,解引用得到了数组最后一个元素5
因为a是数组,a的地址类型是char * 所以需要强制类型转化为 int * 才可以存储到ptr中。

第二题

//假设p的值为0x100000,如下表达式的值分别为多少?
//已知结构体Test类型的变量大小为20个字节
struct Test
	{
	   int Num;
	   char *pcName;
	   short sDate;
	   char cha[2];
	   short sBa[4];
	
	}*p;
int main()
{
	printf("%pn",p + 0x1);//0x100014   p是结构体指针,p+0x1 就是p+1,所以就是跳过一个结构体变量大小,就是跳过20个字节,十六进制就是0x100014
	printf("%pn",(unsigned long)p + 0x1);//0x100001  p的类型强制转化为(ungined long),p+1就是加上1。
	printf("%pn",(unsigned int*)p + 0x1);//0x100004 p的类型强制转化为(ungined int*),p+1就是跳过一个指针,大小是4
   return 0;
}

第三题

int main()
{
	int a[4] = {1,2,3,4};
	int *ptr1 = (int*)(&a+1);//
	int *ptr2 = (int*)((int)a+1);//a作为数组名,在这个代表首元素地址,强制转化为int类型,a+1就是往后加一个字节数组内每一个元素都是4个字节,向后加一个字节,00 00 00 02  又因为内存是小端存储,所以以16进制打印,就为0x02000000
	printf("%x,%x",ptr1[-1],*ptr2);//4 , 200000
	
	return 0;
}

第四题

int main()
{
	int a[3][2] = {(0,1),(2,3),(4,5)};//!!!!注意数组内是(0,1)(2,3)(4,5)这是逗号表达式,逗号表达式的结果是最后一个表达式的结果,所以二维数组存的其实是 1 3 5 0 0 0
	int *p;
	p =a[0];//p拿到的是a[0] 也就是数组第一行的地址
	printf("%d",p[0]);//1    p[0]就是第一行第一个元素
	return 0;
}

第五题

int main()
{
   int a[5][5];
   int(*p)[4];
   p = a;// p的类型为int(*)[4]  a的类型为 int(*)[5]  a强制赋值给p,p指向第一行第一个元素 &p[4][2]就是 *((*(p+4))+2) 地址相减就是中间元素的个数,又因为是低地址减去高地址,所以得出的结果是负数
   printf("%p,%dn",&p[4][2]-&a[4][2],&p[4][2]-&a[4][2]);//    FFFFFFFC , -4
   //-4的原码: 10000000000000000000000000000100
   //    反码:11111111111111111111111111111011
   //    补码: 1111 1111 1111 1111 1111 1111 1111 1100
   //            f   f    f   f     f    f   f    c
   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   
	//&aa+1 跳过了一整个二维数组,ptr1-1 就指向了10
	// *(aa+1) ,aa+1相当于aa[1],ptr2指向了6的地址,ptr2-1就指向5
	return 0;
}

第七题

int main()
{
	char *a[]={"work","at","alibaba"};
	char **pa = a;
	pa++;
	printf("&sn",*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("%sn",**++cpp);//POINT
	printf("%sn",*--*++cpp + 3);//ER
	printf("%sn", *cpp[-2] + 3);//ST
	printf("%sn", cpp[-1][-1]+1);//EW
	return 0;
}

指针与数组笔试题解析
注意的一点是 ++cpp 时cpp的值已经加了1,在后续的计算中 不能使用cpp的原始值,而应该是运算后的值。


程序员灯塔
转载请注明原文链接:指针与数组笔试题解析
喜欢 (0)