欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言八道筆試題精講帶你掌握指針

 更新時間:2022年07月06日 10:48:55   作者:龍兆萬  
C語言這門課程在計算機(jī)的基礎(chǔ)教學(xué)中一直占有比較重要的地位,然而要想突破C語言的學(xué)習(xí),對指針的掌握是非常重要的,本文將具體針對指針的基礎(chǔ)做詳盡的介紹

為了題目的準(zhǔn)確性和我們一般學(xué)習(xí)過程中的習(xí)慣,這里所有的題目代碼都是在 X86 環(huán)境(32 位平臺)下運(yùn)行的。

題目一

#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;
}
//程序的結(jié)果輸出什么?

我們先研究 ptr 指針變量里面存儲的是什么。&a+1 表示取出整個地址并向后跳躍一個數(shù)組類型的大小,也就是指向了數(shù)組最后一個元素 5 的后面一塊數(shù)組類型大小的空間。

但是我們想要把這個地址交給指針變量 ptr 是不行的,因為類型不一樣(&a+1 是一個數(shù)組指針類型,prt 是一個整形指針類型),所以我們在 (&a+1) 之前 (int*) 來強(qiáng)制類型轉(zhuǎn)換。這樣我們搞清楚了 ptr 指針變量里存的是什么。

那么現(xiàn)在來看輸出部分。*(a+1) 是比較簡單的,a 是首元素地址,a+1 是第二個元素地址,對其解引用得到第二個元素 2 ,這是毋庸置疑的答案。對于 *(ptr-1) ,我們知道 ptr 里面存放的地址位置,并且知道 ptr 是一個整形指針,ptr-1 相當(dāng)于向前跳躍一個整形類型的大小,即指向數(shù)組最后一個元素 5 的位置。對其解引用就能得到元素 5 。

故最后的輸出結(jié)果為: 2,5 。

題目二

#include <stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//如下表表達(dá)式的值分別為多少?
//已知,結(jié)構(gòu)體Test類型的變量大小是20個字節(jié)
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}
//程序最后輸出什么?

我們注意觀察結(jié)構(gòu)體的定義,定義了一個結(jié)構(gòu)體指針變量 p 。

p+0x1 非常簡單,0x1 就是 1,只不過是以十六進(jìn)制的格式書寫的。這與我們經(jīng)常習(xí)慣使用的指針計算一樣,p 是一個結(jié)構(gòu)體指針,那么 p+1 理當(dāng)向后跳躍一個結(jié)構(gòu)體類型的大小,即指向了結(jié)構(gòu)體空間的后一個結(jié)構(gòu)體空間的位置。并且我們知道 p 是一個全局變量,全局變量默認(rèn)初始化為 0 ,那我們便可以知道,p=0 ,p+1=20 。而 %p 是一個十六進(jìn)制的打印格式,所以結(jié)果輸出:00000014 。

(unsigned long)p + 0x1 似乎更簡單一些。p 類型轉(zhuǎn)換成了一個長整形,那么就代表 p 不再是一個指針,它存放的 0 就是單純意義上的數(shù)字。所以 0 + 0x1 就等于 00000001 。

(unsigned int*)p + 0x1 也非常簡單。p 本是一個結(jié)構(gòu)體指針,現(xiàn)在強(qiáng)轉(zhuǎn)為整形指針,這就代表著 p 進(jìn)行加減整數(shù)的時候步幅由 20 個字節(jié) 變成了 4 個字節(jié)。那么 p=0 ,p+1=4 是毋庸置疑的。輸出的結(jié)果為:00000004 。

題目三

#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;
}
//程序的結(jié)果輸出什么?

ptr1 的分析與題目一沒有區(qū)別,ptr1 存放的是數(shù)組最后一個元素的后面一塊數(shù)組類型大小的地址。并且 ptr1 是一個整形指針。

ptr1[-1] 可改寫成 *(ptr-1) ,因為我們曾經(jīng)說過,只要是數(shù)組下標(biāo)的操作都是指針操作,數(shù)組下標(biāo)的操作只是指針操作的簡寫。那么此時 ptr1[-1] 就應(yīng)該指向數(shù)組最后一個元素 4 并對其解引用得到輸出結(jié)果 00000004 。

(int*)((int)a+1) 如何理解呢?a 是數(shù)組名,那么它就指向了數(shù)組首元素的地址,再將其強(qiáng)制類型轉(zhuǎn)換,那么 a 里面存放的地址就是單純意義上的數(shù)字,我們在這個數(shù)字的基礎(chǔ)上 +1 ,然后再強(qiáng)制類型轉(zhuǎn)換成整形指針并存放在 ptr2 中。也就是說,a 本是指向數(shù)組首元素的地址,(int)a+1 就代表地址數(shù) +1 ,地址數(shù) +1 就說明如果是指針的話,它就會指向后一個字節(jié)。再強(qiáng)轉(zhuǎn)為整形指針,那么此時 ptr2 指向的地址為:

再對其解引用就能找到紅色方塊那塊空間的內(nèi)容,因為是小端存儲,那么輸出的結(jié)果是:02000000 。

需要注意的是,本題使用的打印格式為 %x ,正兒八經(jīng)的十六進(jìn)制,會省略有效數(shù)字前的 0 。

題目四

#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;
}
//程序的結(jié)果輸出什么?

首先我們注意觀察,二維數(shù)組 a 里面存放的是三個逗號表達(dá)式,我相信有人會在這里踩坑。即三個逗號表達(dá)式,那么二維數(shù)組 a 里面的內(nèi)容應(yīng)該是 1,3,5 ,0,0,0 (數(shù)組 a 有 6 個元素,內(nèi)容不夠后面自動補(bǔ) 0 )。

搞清了二維數(shù)組存放的是什么之后,我們來研究 a[0] 是什么。a[0] 是二維數(shù)組的第一個元素,這個元素是一個數(shù)組,也就是說,指針變量 p 存放的是二維數(shù)組中的第一個元素,這個元素是一個一維數(shù)組,即拿到了一個數(shù)組名。那么 p[0] 就很好理解了,p 是一個數(shù)組名,p[0] 就是數(shù)組的首元素,即 1 。故輸出 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;
}
//程序的結(jié)果輸出什么?

我們可以看到,數(shù)組指針 p 存放了二維數(shù)組 a 的首元素地址,這就不難分析了,p 指向的數(shù)組與 a 數(shù)組的存儲內(nèi)容一樣,但是內(nèi)存分配不一樣。

我們把這兩個空間重疊在一起:

可以看到,&p[4][2] 與 &a[4][2] 相差了 4 個元素,但因為 &p[4][2] 的地址位置比較低,所以兩個相減是一個負(fù)數(shù),即 -4 。但我們要以 %p 的形式打印,%p 是一個無符號的數(shù),所以我們便得知結(jié)果應(yīng)該是一個非常大的十六進(jìn)制數(shù)。那么 -4 的原反補(bǔ)為:

所以前者的輸出結(jié)果為:fffffffc 。

我們知道,指針(地址)相減,得到的是相差的元素個數(shù),上面我們也講過。那么 %d 是一個有符號的打印格式,所以輸出的結(jié)果就是 -4 。

題目六

#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;
}
//程序的結(jié)果輸出什么?

*(ptr1-1) 的結(jié)果為 10 應(yīng)該沒什么意見吧?

*(aa+1) 可改寫成 aa[1] ,也就是二維數(shù)組的第二個元素,這個元素是一個一維數(shù)組,也就是說得到了一個數(shù)組名。將這個數(shù)組名強(qiáng)轉(zhuǎn)為整形指針存放在指針變量 ptr2 中,這時候就知道了 ptr2 的具體指向位置。(二維數(shù)組在內(nèi)存空間中是連續(xù)存放的!)

*(ptr2-1) 就是將 ptr2 向前跳躍一個整形類型的大小,并解引用,即找到了元素 5 ,所以輸出結(jié)果為 5 。

題目七

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}
//程序的結(jié)果輸出什么?

指針數(shù)組 a 存放了三個字符串常量(關(guān)于字符串的常量在往期的博客中已經(jīng)介紹過),使用二級指針 pa 來指向這個數(shù)組(char** pa=a;),這就表明 pa 變量存放的是 a 數(shù)組的首元素地址。pa++ 指向了數(shù)組的第二個元素,*pa 毋庸置疑得到了字符串常量 "at" 的首元素地址,再通過 %s 打印,就能的得到 at 。

題目八

#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;
}
//程序的結(jié)果輸出什么?

我們先分析一下 c、cp、cpp 里面存放的是什么東西。指針數(shù)組 c 里面存放有四個字符串常量。指針數(shù)組 cp 里面存放的是四個字符串常量的地址。三級指針 cpp 存放的是 指針數(shù)組 cp 的首元素地址。那么草圖可以畫成:

**++cpp ,因為結(jié)合性的原因,我們要先計算 ++cpp,那么此時 cpp 指向 cp 的第二個元素的地址,然后解引用得到了 cp 中第二個元素,這個元素又是指向 c 的第三個元素,然后再解引用得到 c 的第三個元素,這個元素是字符串常量 "POINT" 的首字符地址,通過 %s 的形式打印得到 POINT 。一定要注意,++ 這個操作是 cpp 參與運(yùn)算了,所以下次運(yùn)算時會從計算后的位置開始。

*--*++cpp+3 ,還是先計算 ++cpp ,此時 cpp 指向 cp 的第三個元素的地址,然后解引用得到 c+1 ,然后 -- ,c+1 就變成了 c ,然后解引用得到 c 的首元素地址,在此地址的基礎(chǔ)上 +3 ,就拿到了字符串常量 "ENTER" 的第四個字符的地址,然后通過 %s 的形式打印得到 ER 。

*cpp[-2]+3 可改寫為 *(*(cpp-2))+3 ,也就是說,此時 cpp 指向了 cp 的首元素地址,解引用得到了 c+3 ,c+3 是指向 c 的第四個元素的地址,解引用便得到了 c 的第四個元素,這個元素是字符串常量 "FIRST" 的首元素地址,在此地址的基礎(chǔ)上 +3 便得到字符串常量第四個字符的地址,%s 通過這個地址打印便得到 ST 。(此時 cpp 是沒有實(shí)質(zhì)運(yùn)算的)

cpp[-1][-1]+1 可改寫為 *(*(cpp-1)-1)+1 ,此時 cpp 指向 cp 的第二個元素的地址,解引用得到 c+2 ,然后 -1 得到 c+1 ,即指向了 c 的第二個元素的地址,解引用便得到了 c 的第二個元素,這個元素是字符串常量 "NEW" 的首元素地址,然后 +1 便指向了字符串常量的第二個字符的地址,通過 %s 形式打印便得到了 EW 。

到此這篇關(guān)于C語言八道筆試題精講帶你掌握指針的文章就介紹到這了,更多相關(guān)C語言指針內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C語言實(shí)現(xiàn)商品管理系統(tǒng)開發(fā)

    C語言實(shí)現(xiàn)商品管理系統(tǒng)開發(fā)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)商品管理系統(tǒng)開發(fā),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Matlab實(shí)現(xiàn)生成箭頭坐標(biāo)軸詳解

    Matlab實(shí)現(xiàn)生成箭頭坐標(biāo)軸詳解

    這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)生成箭頭坐標(biāo)軸,為坐標(biāo)軸增添箭頭,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Matlab有一定幫助,需要的可以參考一下
    2022-03-03
  • C語言中printf()緩沖問題詳解

    C語言中printf()緩沖問題詳解

    這篇文章主要給大家介紹了關(guān)于C語言中printf()緩沖問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • C語言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng)

    C語言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言代碼實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 簡單介紹C++中變量的引用

    簡單介紹C++中變量的引用

    這篇文章主要簡單介紹了C++中變量的引用,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • VScode搭建OpenCV環(huán)境的詳細(xì)步驟

    VScode搭建OpenCV環(huán)境的詳細(xì)步驟

    用vscode來寫opencv代碼需要自己編譯OpenCV,主要用到MinGW-w64和CMake工具。接下來通過本文給大家介紹VScode搭建OpenCV環(huán)境的相關(guān)知識,需要的朋友可以參考下
    2021-11-11
  • C++ 虛函數(shù)表圖文解析

    C++ 虛函數(shù)表圖文解析

    最近學(xué)了設(shè)計模式中的簡單工廠模式,對多態(tài)有了具體的認(rèn)識。于是補(bǔ)了補(bǔ)多態(tài)、虛函數(shù)、虛函數(shù)表相關(guān)的知識,本文介紹了C++ 虛函數(shù)表,感興趣的了解一下
    2021-05-05
  • C++利用socket傳輸大文件的實(shí)現(xiàn)代碼

    C++利用socket傳輸大文件的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了C/C++如何使用socket傳輸大文件的實(shí)現(xiàn)代碼,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下
    2023-10-10
  • C++中如何將數(shù)據(jù)保存為CSV文件

    C++中如何將數(shù)據(jù)保存為CSV文件

    這篇文章主要介紹了C++中如何將數(shù)據(jù)保存為CSV文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++深入講解namespace與string關(guān)鍵字的使用

    C++深入講解namespace與string關(guān)鍵字的使用

    namespace命名空間或者叫名字空間,傳統(tǒng)的c++只有一個全局的namespace,namespace引入了復(fù)雜性。namespace允許像類,對象,函數(shù)聚集在一個名字下。本質(zhì)上講namespace是對全局作用域的細(xì)分
    2022-05-05

最新評論