目录
前言
C语言指针笔试题
一、运行结果?
#include<stdio.h>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int* ptr = (int*)(&a + 1);//&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
printf("%d,%d", *(a + 1), *(ptr - 1));
return 0;
}
&a得到的是数组的地址,&a+1,跳过整个数组,用ptr指向这个位置,ptr-1指向上图位置,然后解引用得到后的int类型的数据,得到5
二、运行结果?
1.结构体对齐规则
一、结构体对齐规则首先要看有没有用#pragma pack宏声明,这个宏可以改变对齐规则,
有宏定义的情况下结构体的自身宽度就是宏上规定的数值大小,所有内存都按照这个宽度去布局,
#pragma pack 参数只能是 '1', '2', '4', '8', or '16'。
二、在没有#pragma pack这个宏的声明下,遵循下面三个原则:
1、第一个成员的首地址为0.
2、每个成员的首地址是自身大小的整数倍
3、结构体的总大小,为其成员中所含最大类型的整数倍。
2.运行结果
假设p 的值为0x100000。 如下表表达式的值分别为多少?
1)首先定义了一个结构体类型的指针p,即p的类型为(struct Test*),现在让p的地址是0x100000,本题考察点就是指针+1跳过了几个字节,指针+1取决于类型,int* +1 跳过4个字节,char* +1 跳过1个字节;
2)p的类型为(struct Test*),所以 + 1后跳过20个字节,0x100000,指针+1,跳过20个字节,那就是0x100014,14(16进制)->20(十进制);
3)进行(unsigned long)强制类型转换后,p变为了一个普通的整形数字,数字+1后就是加1变成0x100001,对于整形+1,相当于向后走了一个字节,因为数字+1,相当于地址本来是0x10的地址+1,我们将10变成十进制是16,16+1就是17,而17其实就是0x11,其实就是0x10直接+1就行,因为1*16^0 = 1。一个字节差一个地址,在内存单元中,一个地址给一个编号。其0x16和0x17差一个地址,其实际就是差一个字节;
4)在进行(unsigned int*)强制类型转换后,加1跳过一个整型的大小,即4个字节。
struct Test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
int main()
{
p = 0x100000;
printf("%x\n", p + 0x1);//%p是以地址的形式打印,%x打印16进制,但省略高位的0
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
三、运行结果?
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);
//ptr1跳过了整个数组
//ptr1[-1]->ptr1[0+(-1)]->*(ptr1-1)->4->0x4
return 0;
}
四、运行结果?
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//注意逗号表达式
int* p;
p = a[0];//a[0]代表的就是第一行的地址,与第一行第一个元素地址相同
printf("%d", p[0]);//1->*(p+0)->*p
return 0;
}
五、运行结果?
int main()
{
int a[5][5];
int(*p)[4];//定义一个指针,指针指向一个数组,数组有4个元素,元素都是int类型的
p = a;//然后该指针存放二维数组的地址
printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
return 0;
}
假设有 a[n] ,表示a向下偏移n行后的地址;
假设有*(a+n),表示向下偏移n行后的地址;
六、运行结果
注意类型:
输出结果:
七、运行结果?
先看char *a[] :
由于[] 的优先级高于 * 所以a先和 []结合,他还是一个数组,数组中的元素才是char * ,char * 是一个变量,保存的地址。
char *a[] = {"China","French","America","German"};
通过这句可以看到, 数组中的元素是字符串,那么sizeof(a) 是多少呢,有人会想到是五个单词的占内存中的全部字节数 6+7+8+7 = 28;但是其实sizeof(a) = 16;
为什么, 字符串常量的本质是地址,a 数组中的元素为char*指针,指针变量占四个字节,那么四个元素就是16个字节了。
#include <stdio.h>
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);//%s输出字符串的时候遇到0或‘\0’,就会被截断,只输出0或‘\0’前面的字符
printf("%s\n", *-- * ++cpp + 3);
printf("%s\n", *cpp[-2] + 3);
printf("%s\n", cpp[-1][-1] + 1);
return 0;
}
注意:cpp[-2]我们可以把它当做解引用,并没有做运算,所以cpp的值,还会延续第三步结束时的值。
总结
指针笔试题,值得反复去看,一篇足够!