第一題(注意)
1.下列 C 代碼中,不屬于未定義行為的有:______。
A:int i=0; i=(i++);
B:char *p="hello"; p[1]='E';
C:char *p="hello"; char ch=*p++;
D:int i=0; printf("%d %d\n",i++,i--);
答案及解析 C
????????未定義行為是指C語言標準未做規定的行為。同時,標準也從沒要求編譯器判斷未定義行為,所以這些行為有編譯器自行處理,在不同的編譯器可能會產生不同的結果,可能報錯,可能正常運行,可能運行結果不同。
未定義行為:
1.變量即是左邊結果,又是右邊的操作數,如a+=a++,a %= b ^= a ^= b ^= a
2.使用越界數組也是C的一個“未定義行為”
3.允許一個隨便指的指針的讀寫。
4.使用未初始化的變量5.改變字符串常量
A:經典的變量即是左邊結果,又是右邊操作數,屬于未定義行為;
B:首先p指向的是字符串常量,修改字符串常量也是未定義行為;
C:定義了一個字符串常量,后面的ch是取的*p++,先p++,p存的是hello的首元素地址,是p的地址,p++指向e,解引用之后取到的是e,ch = e。只是賦值,沒有改變字符串常量,不是未定義行為;
D:在printf語句中i++和i--無法確定誰先運行,是未定義
相關博客:C/C++未定義行為的例子匯總-CSDN博客
第二題
2.下面程序輸出為()
#include <stdio.h>
int fun(int a) {int b = 0;static int c = 3;b++;c++;return (a+b+c);
}int main( ) {int i=0;for(; i < 3; i++)printf("%d",fun(2));return 0;
}
A:777
B:789
C:7911
D:71320
答案及解析 B
本題考查的是局部的static變量(靜態變量)的相關知識,我們要知道,局部靜態變量只會初始化一次,然后后續變化都會累加;
第三題(有異議)
3.下列敘述中,錯誤的是:
A:計算機不能直接執行C語言編寫的源程序。
B:C程序經編譯后,生成的擴展名為.obj的文件是一個二進制文件。
C:擴展名為.obj的文件,經鏈接程序生成擴展名為.exe的文件是一個二進制文件。
D:擴展名為.obj和.exe的二進制文件都可以直接運行。
答案及解析 D
本題是考查大家對翻譯環境的理解,關于翻譯環境的博客:通過歷史 --> 了解翻譯環境(預處理、編譯、匯編、鏈接)-CSDN博客
A:計算機只識別二進制指令,所以要通過預處理--> 編譯?--> 匯編?--> 鏈接 才能傳給計算機
B:這里的B選項不嚴謹,準確來說編譯生成的是.s的文件,并不是我們的obj文件,因為我們的編譯器是會先把.c 文件經過預處理先生成.i文件,之后對.i文件進行編譯翻譯成我們的匯編代碼生成.s文件,之后才是經過匯編翻譯成我們的.obj/.o這樣的目標文件,但是目標文件是不能夠執行的,還需要通過鏈接,找到對應的動態庫啊或者靜態庫這樣的,為的是找到你調用的函數的定義。
????????這里的不嚴謹取決你的編譯器是直接將C語言翻譯成二進制指令,還是要先把C轉換成匯編,再由匯編變成二進制,如果是前者,就是對的,后者就是錯的。其實一般就是轉為匯編,畢竟我們先有匯編變成二進制的編譯器啊,站在巨人的肩膀上嘛!而且C語言和匯編還相似,所以我才會說這里不嚴謹,畢竟計算機這門學科應該是發展性,繼承性的學科,而不是我發明了個新的東西,要重新開始寫所有的東西。但是D是最錯的,所以就是D了。
????????在牛客網本題的評論就是本人發的,沒有存在抄襲哦
C:這是對的,.obj的文件通過鏈接之后才形成.exe的可執行程序;
D:記住.obj/.o只是目標文件,還沒有找到對應的函數定義,所以無法執行,需要通過鏈接尋找動態庫或者靜態庫,才可以找到函數的定義,進而生成可執行的.exe文件。
第四題
4. 設有 int x=11; 則表達式 (x++ * 1/3) 的值是( )
A:3
B:4
C:11
D:12
答案及解析 A
本題考查的是優先級的問題,這里就不做解釋
相關博客:C語言操作符優先級表格(建議收藏,每次看一下)-CSDN博客
第五題
5. 在 gcc 環境下,已知數組 int arr[5]={1,2,3,4,5}; 則 *(*(&arr+1)-1) 的結果為
A:1
B:0
C:4
D:5
答案及解析 D
本題是考查的&arr代表的是什么?
本身arr代表的是數組首元素地址,&arr是取出整個數組的地址,那他就相當于一個指針變量里存放一整個數組的地址,如何把一個數組的地址都存進去呢?就是把數組每個元素的地址,變成一個指針數組,再放在這個指針變量中,所以這個變量也就是二級指針,這樣說其實很抽象,大家可以看圖來理解。既然&arr是一個二級指針,加一就是跳過的一個數組,我們還需要知道地址是連續的,所以&arr+1指向的就是這里,但是實際就是5的地址后面的地址,因為是跳過一整個數組的地址,*(arr+1)就是解引用,取到的是一級指針,也就是5后面的地址,*(arr+1)- 1 就是對這個地址減1,減少的就是sizeof(int)的大小,就是5的地址,再解引用就是5了。