文章目錄
- 筆試題一
- 筆試題二
- 筆試題三
- 筆試題四
- 筆試題五
- 筆試題六
- 筆試題七
- 筆試題八
筆試題一
#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;
}
// 程式的結果是什么?
要想答對這道題,首先要知道 &陣列名 和 陣列名 的區別.
&陣列名 : 這里的陣列名表示整個陣列,取出的是整個陣列的地址,&陣列名 + 1 跳過整個陣列,&陣列名為陣列指標型別,在該題中即為 int (*)[5] 型別
陣列名 : 陣列名為首元素的地址,+ 1 跳過一個元素型別大小的位元組,為 int *型別
雖然 &陣列名 和 陣列名 以 %p 的形式列印出來結果是一樣的,但一定要注意它們之間的區別,

因此結果為 2,5
筆試題二
#include<stdio.h>
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); // 0x100014
printf("%p\n", (unsigned long)p + 0x1); // 0x100001
printf("%p\n", (unsigned int*)p + 0x1); // 0x100004
return 0;
}
這題考察的是 強制型別轉換 和 不同型別指標的區別.
不同型別指標的區別 :
1.加減整數所走的步長不一樣.
2.解參考后訪問的權限不一樣.
第一個p是指向結構體的指標,加1跳過一個結構體,0x100000 + 20 = 0x100014
第二個p為無符號長整形,加1直接加1 0x100000 + 1 = 0x100001
第三個p是指向無符號整形的指標,加1跳過一個無符號整形,0x100000 + 4 = 0x100004
筆試題三
#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);
return 0;
}
// 輸出結果是什么?
如果有讀者對大小端的存盤模式不清楚的話,可以去看一下這篇博客
資料在記憶體中的存盤(整數)
筆試題四
#include <stdio.h>
int main()
{
int a[3][2] = { 1, 3, 5 };
int *p;
p = a[0];
printf("%d", p[0]);
return 0;
}
// 輸出結果是什么?
解決這道題,我們首先要理解二維陣列.
對于 int[3][2],我們可以把它看作一個一維陣列,一維陣列里有三個元素,每個元素為一個陣列(存放兩個整形)
a[0],a[1],a[2] 分別是每一行的陣列名,即每一行首元素的地址.
二維陣列的陣列名同樣表示首元素的地址,首元素為a[0],即 &a[0],為陣列指標型別.

結果為 1
筆試題五
#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;
}
p[4] 等價于 *(p + 4) , 因為p為陣列指標型別,+ 1 跳過 一個陣列,解參考后得到首元素的地址,這里要理解 *(&陣列名) 和 陣列名 是等價的

筆試題六
#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;
}
// 輸出結果為多少?
該題和 第一題,第三題很相似,讀者們可以放在一起加深理解
因此結果為 5,10
筆試題七
#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;
}
// 輸出結果為多少?
這里要注意的點是 括號運算式 ,括號運算式的計算結果只取決于最后一個運算式的計算結果 , 原代碼相當于:
int a[3][2] = { 1,3,5 };
因此該題結果為 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);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
// 輸出結果是什么?

**++cpp : 等價于 **(++cpp)
1.++cpp后,cpp指向了cp[1] , 因為是前綴++ , 先++后使用 , 第一次解參考后得到cp[1]的內容,即c[2]的地址 .
2 第二次解參考后,拿到c[2]的內容 , 即字串"POINT"的首地址,即 ‘p’ 的地址, 因此列印結果為 POINT
第一步進行完后,指向如下:
*-- *++cpp + 3 : 等價于 ( *( -- ( * (++cpp) ) ) ) + 3
1.++cpp后,cpp指向了cp[2] , 解參考后得到了cp[2]的內容,即c[1]的地址
2.前綴 - -后,cp[2]的內容被改成c[0]的地址
3.解參考后拿到c[0]的內容,即字串"ENITR"的首元素地址,即字符 'E’的地址
4 . +3 后,得到第二個字符 'E’的地址,因此列印結果為 ER
第二步進行完后,指向如下:

* cpp[-2]+3 : 等價于 *( *(cpp - 2) ) + 3
1 . cpp - 2指向了cp[0] , 解參考后得到cp[0]的內容,即c[3]的地址
2 .第二次解參考后得到c[3]的內容,即字串" FIRST"首字符的地址,即字符 ’ F’的地址
3 .+3后,得到字符 'S '的地址,列印結果為 ST
第三步進行完后,指向如下:
注意喔 : cpp的指向可沒有改變,一定要小心喔!!!

cpp[-1][-1]+1 : 等價于 *( *(cpp - 1) - 1) + 1
1 . cpp - 1指向cp[1] , 解參考得到cp[1]的內容,即c[2]的地址
2 .- 1 后得到c[1]的地址 ,解參考得到c[1]的內容,即字符 'N’的地址
3 . +1后得到字符 'E’的地址,列印結果為 EW
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/257176.html
標籤:其他
上一篇:STM32F103最小系統板制作FPV穿越機(從零到起飛全面教程!)
下一篇:2021美賽B題
