题目一:
请输入以下程序的结果
#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)); //2 5
return 0;
}
解析:
- &a 表示取得数组a存储区域的首地址(类型是 int[5] *)
- *(a +1) == a[1]
- 则 &a+1 得到的是数组a存储区域的后的地址
- ptr指针指向数组的最后一个元素后面的那个存储单元的地址,而ptr减1后,再进行数据访问,则访问的是ptr指针的前一个存储单元(a[4])的值
题目二:
#include <stdio.h>
int main()
{
int a = 6;
int *p = &a;
printf("%p\n", p); //0098F97C
printf("%p\n", p + 0x1);//0098F980
printf("%p\n", (unsigned long)p + 0x1);//0098F97D
printf("%p\n", (unsigned int*)p + 0x1);//0098F980
return 0;
}
解析:
- 指针指向的基类型不一样,虽然加的单元数是一样的,但字节数是不一样的( 0x1 == 1)
- p 是一个指针类型(int *),所以 p 与 p + 1 相差4个字节
32位处理器可以一次性处理4个字节的数据量,所以是4个字节;
64位处理器可以一次性处理8个字节的数据量,所以是8个字节。
- (unsigned long)p 将 p 强转为无符号整型,所以 p 与 p + 1 相差 1
- (unsigned int*)p 基类型还是一个指针类型,所以 p 与 p + 1 相差4个字节
题目三:
#include <stdio.h>
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); //4 2000000 = 0x02000000
return 0;
}
解析:
- ptr1[-1] 参考题目1
大端:把高位存储到低地址里面,把低位存储到高地址里面
小端:把低位存储到低地址里面,把高位存储到高地址里面
计算机小端模式存储数组a的数据:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00
- (int)a + 1;指向了整个数组内存块的第二个地址,即指向a[0]第二个字节处的地址( 00 00 00 02 ),再以16进制输出( 00 00 00 02 )即 2000000
题目四:
#include <stdio.h>
int main()
{
int a[3][2] = { (0, 1), (2, 3), (4, 5) };
int *p;
p = a[0];
printf("%d", p[0]);// 1
return 0;
}
解析:
- 请参考运算符(逗号表达式)
- int a[3][2] = { 1, 3, 5, 0, 0, 0 };
题目五:
#include <stdio.h>
int main() {
int a[5][5];
int(*p)[4];
p = a;
printf("%d\n", &p[4][2] - &a[4][2]);//-4
return 0;
}
解析:
- p[4][2]偏离首元素位置为18
- a[4][2]偏离首元素位置为22
题目六:
#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));//10 5
return 0;
}
解析:
- &aa 取到的是整个数组的地址
- &aa + 1 得到的是数组a存储区域的后的地址
- *(aa +1) == aa[1][0]
题目七:
#include <stdio.h>
int main() {
char *a[] = { "work", "at", "alibaba" };
char **pa = a;
pa++;
printf("%s\n", *pa);//at
return 0;
}
解析:
- pa++ == * *(pa + 1)
题目八:
#include <stdio.h>
int main() {
char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
char **cp[] = { c + 3, c + 2, c + 1, c };
char ***cpp = cp;
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;
}
解析:
- *cpp[-2] == *(cpp - 2)
- cpp[-1][-1] == * ( *(cpp - 1)- 1)
题目九:
#include <stdio.h>
int main()
{
char *str[] = { "welcome", "to", "Fortemedia", "Nanjing" };
char**p = str + 1;
str[0] = (*p++) + 2;
str[1] = *(p + 1);
str[2] = p[1] + 3;
str[3] = p[0] + (str[2] - str[1]);
printf("%s\n", str[0]);//to后的'\0'
printf("%s\n", str[1]);//Nanjing
printf("%s\n", str[2]);//jing
printf("%s\n", str[3]);//g
return 0;
}
解析:
题目十:
数组a的定义语句为“float a[3][4];
”,下列()是对数组元素不正确的引用方法。
A. a[i][j]
B. * (a[i]+j)
C. * ( * (a+i)+j)
D. * (a+I*4+j)
正确答案:
D
答案解析:
*(a+i*4+j)
中的a是个数组指针,应该这样写
*(*a+i*4+j)
题目十一:
二维数组X按行顺序存储,其中每个元素占1个存储单元。若X[4][4]的存储地址为Oxf8b82140,X[9][9]的存储地址为Oxf8b8221c,则X[7][7]的存储地址为()。
A. Oxf8b821c4
B. Oxf8b821a6
C. Oxf8b82198
D. Oxf8b821c0
正确答案: A
答案解析:
我们先来看以下的数组:
从上图直观的看出 X[9][9] 与 X[4][4] 相差 5n - 5 个元素,则有以下计算公式:
[9][9] - [4][4] = 21c-140=5n+5 (1)
[7][7] - [4][4]=x- 140 =3n+3 (2)
[7][7] = 140+3/5*( 21c-140 )= 1c4 (3)
说明:
- (1)中相减为 DC 为16进制,转换为十进制为 220 算出 n 为 43
- (2)中计算得出 x 为 1c4 ,切记16进制与十进制的转换。
如有错误,欢迎留言指点!!!