目录
笔试题1:
笔试题2:
笔试题3:
笔试题4:
笔试题5:
笔试题6:
笔试题7:
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
详细分析:
&a-------int(*)[5](类型),如果要将&a赋值给p,则有int (*p)[5] = &a
&a是数组的地址,&a+1跳过整个数组
将&a+1强制类型转换为和指针变量ptr相同的类型,ptr-1表示减去一个整型的地址
*(a+1):a是数组名,表示首元素地址,a的类型为(int*),如图a位置,加1表示跳过一个元素,指向2的位置,如图a+1,解引用后值为2。
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;
}
程序的结果是什么呢?
运行代码:
则答案为 00100014 00100001 00100004
详细分析:
p+0x1:表示p+1,指针加1(取决于指针类型——结构体指针),此结构体类型的大小为20个字节,所以增加20,而地址的表示方法是16进制,20的16进制为14,最终结果为00100014。
(unsigned long)p+0x1:p是一个结构体指针类型,将结构体指针类型强制类型转换为unsigned long类型,整形加1就是加1,结果为00100001。
(unsigned int*)p+0x1:将结构体指针类型强制类型转换为unsigned int*类型,整形指针+1,跳过4个字节,最终结果为00100014。
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;
}
程序的结果是什么呢?
运行代码:
则答案为 4 2000000
详细分析:
%p --------- 是打印地址
%x --------- 是16进制的格式打印
&a+1:增加一个数组a的大小;将其转化为int*类型在赋给指针变量ptr1。如图所示
(int)a + 1:a是一个数组名,表示首元素地址,首元素的地址强制类型转换为整形,整形加一就是加一,跳过一个字节;将其转化为int*类型在赋给指针变量ptr2。
ptr1[-1] -------> *(ptr1-1)
ptr1为一个整型指针,整形指针减一,即向前移一个整型,如图所示 ptr1-1,解引用向后访问四个字节(04 00 00 00),即为4
ptr2为一个整型指针,解引用向后访问4个字节,如图所示(00 00 00 02),假设是小端放入,还原回来就是(02 00 00 00),16进制打印出来就是0x2000000
#include
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
程序的结果是什么呢?
运行代码:
则答案为 1
详细分析:
区别于:int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };
原题为逗号隔开的表达式,表达式结果为:int a[3][2] = { 1, 3, 5 };
a[0]:第一行的数组名,没有单独放入sizeof内部,数组名表示首元素地址。相当于&a[0][0]
p[0] ---------> *(p+0)
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;
}
程序的结果是什么呢?
运行代码:
则答案为 FFFFFFFC -4
详细分析:
int (*p)[4]:p为一个指针,指向一个数组,是四个元素,每个元素是整形
把a赋值给p,a是一个数组名(表示首元素的地址),即二维数组的第一行地址
a--------->int (*)[5]类型 p------->int (*)[4]类型
p+1:跳过4个整形
p[4][2] -----------> *(*(p+4)+2):对于p+4(数组指针)解引用有权利会访问到4个整形元素
&p[4][2] - &a[4][2]:指针和指针相减得到的是指针之间的元素个数,是小地址减大地址(负数),得到-4,
-4:以%d打印就是 -4,以%p(地址)打印就是 FFFFFFFC 如图所示(内存以补码的形式存储)
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;
}
程序的结果是什么呢?
运行代码:
则答案为 10 5
详细分析:
二维数组的本质是一维数组,比如此题的数组aa表示数组内含有两个元素,分别是两个一位数组,
而这两个一维数组又分别包含五个元素。
&aa+1:aa表示整个数组的地址,加1为跳过整个数组。
*(aa+1):aa为数组首元素的地址(第一行的地址),加1(第二行地址),解引用得到第二行(*(aa+1) ---------> aa[1]----第二行的数组名没有单独放入sizeof内部,也没有取地址,表示首元素地址,即&aa[1][0])
ptr1和ptr2都为指针,指针减整型,减去存储内存的元素的类型。
ptr1-1:向前移动一个整型指针,解引用得到10
ptr2-1:向前移动一个整型指针,解引用得到5
#include
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
程序的结果是什么呢?
运行代码:
则答案为 at
详细分析:
char* a[]为指针数组,是数组用来存放指针,该数组有三个元素,分别是三个字符串的地址。
pa = a:是将数组a的首元素的地址放入二级指针变量pa中。
pa++:跳过一个char*的元素
*pa:此时pa为a[1],也就是第二个元素表示字符串的首地址,以%s的形式输出,依次打印字符串。