1.1 题目一
#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)则跳过了整个数组,而a为数组首元素地址,因此(a+1)表示数组第二个元素的地址,*(a+1)表示第二个元素2,ptr-1表示跳过一个字节指向5,因此*(ptr-1)表示5,代码运行结果如下:
在这里我们还要理解的问题是,为什么&a+1的类型需要强制转化,这说明&a+1的类型不是int*,
那它是什么类型呢?我们知道,&a为真个数组的地址,如果要使用一个指针接收它,那么我们需要用到数组指针,即int (*P)[5]=&a; 因此&a的类型为int (*)[5],因此为了要达到下面ptr-1跳过一个整形的目的,我们需要强制转换为int*类型。
1.2 题目二
#include<stdio.h>
//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?
struct test
{
int Num;
char* pcName;
short sDate;
char cha[2];
short sBa[4];
}*p = (struct Test*)0x100000;
int main()
{
printf("%p\n", p + 0x1);
printf("%p\n", (unsigned long)p + 0x1);
printf("%p\n", (unsigned int*)p + 0x1);
return 0;
}
p的类型为struct Test*,且结构体大小为20个字节,即p+0x1跳过20个字节
(unsigned long)p把p强制转换为unsigned long类型,此时p不再是指针了,+0x1只是单纯的加1
(unsigned int)p把p强制转化为unsigned int类型,此时+0x1跳过4个字节
运行结果如下:
1.3 题目三
#include<stdio.h>
int main()
{
int a[3][2] = { (0,1),(2,3),(4,5) };
int* p;
p = a[0];
printf("%d", p[0]);
return 0;
}
a[0]可以理解为第一行的数组名,表示第一行的首元素地址,即p为二维数组第一行首元素地址,所以p[0]表示第一行的首元素,而我们可以看到,在对数组赋值的时候,题目使用的是逗号表达式,相当于int a[3][2]={1,3,5}; 因此p[0]为1,运行结果如下:
1.4 题目四
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>
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;
}
这道题目,我们可以先画出数组a在内存中的存储状态图,其中a[4][2]的位置我们很容易得到,但是p[4][2]就比较困难了,首先我们看到p的类型为int(*)[4],它是一个数组指针,这表示p指向的数组只有4个元素,现在将数组a的首元素地址赋值给p,则p[0](第一行的首元素地址)指向上图的位置,则p[2],p[3],p[4]依次指向图中的位置,因此得到&p[4][2]指向的位置,我们知道,同类型的地址相减表示两地址间的元素个数,从图中我们看到,这两个地址相差4个元素,且打印的时候为低地址减高地址,故以%d打印的时候为-4,而以%p打印时,是不会区分符号的,而-4的原码二进制表示形式为10000000 00000000 00000100,因此%p会将这个数打印出来,运行结果如下:
1.5 题目五
#include <stdio.h>
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为整个数组的地址,&aa+1跳过整个数组,它被强制转化为int*赋值给ptr1
aa为数组首元素地址,即第一行的地址,aa+1跳过第一行指向第二行,为第二行的地址,相当于&aa[1],因此*(aa+1)相当于*&aa[1]==aa[1],即数组第二行的首元素地址
因此*(ptr1-1)=10 *(ptr2-1)=5
运行结果如下:
1.6 题目六
#include <stdio.h>
int main()
{
char* a[] = { "work","at","alibaba" };
char** pa = a;
pa++;
printf("%s\n", *pa);
return 0;
}
//请问输出结果是什么?
a为一个数组指针,表示数组首元素地址,它被赋值于pa,数组a有3个元素每个元素的类型为char*,每个元素指向一个常量字符串的首元素地址,因此pa++指向数组第二个元素,*pa得到数组第二个元素,运行结果如下: