1. 程式人生 > >C語言面試題2

C語言面試題2

預處理

問題1什麼是預編譯?何時需要預編譯?

答:

預編譯又稱預處理,是整個編譯過程最先做的工作,即程式執行前的一些預處理工作。主要處理#開頭的指令。如拷貝#include包含的檔案程式碼、替換#define定義的巨集、條件編譯#if等。.

何時需要預編譯:

1、總是使用不經常改動的大型程式碼體。

2、程式由多個模組組成,所有模組都使用一組標準的包含檔案和相同的編譯選項。在這種情況下,可以將所有包含檔案預編譯為一個預編譯頭。

 

問題2寫一個標準巨集,這個巨集輸入兩個引數並返回較小的一個

:#define MIN(x, y) ((x)<(y)?(x):(y)) //

結尾沒有;

 

問題3###的作用?

答:#是把巨集引數轉化為字串的運算子,##是把兩個巨集引數連線的運算子。

例如:

#define STR(arg) #arg          則巨集STR(hello)展開時為”hello”

#define NAME(y) name_y      則巨集NAME(1)展開時仍為name_y

#define NAME(y) name_##y    

則巨集NAME(1)展開為name_1

#define DECLARE(name, type) typename##_##type##_type

則巨集DECLARE(val, int)展開為int val_int_type

問題4:如何避免標頭檔案被重複包含?

答:

例如,為避免標頭檔案my_head.h被重複包含,可在其中使用條件編譯:

#ifndef _MY_HEAD_H

#define _MY_HEAD_H    /*空巨集*/

/*其他語句*/

#endif

關鍵字

問題1static關鍵字的作用?

答:

Static

的用途主要有兩個,一是用於修飾儲存型別使之成為靜態儲存型別,二是用於修飾連結屬性使之成為內部連結屬性。

1靜態儲存型別:

在函式內定義的靜態區域性變數,該變數存在記憶體的靜態區,所以即使該函式執行結束,靜態變數的值不會被銷燬,函式下次執行時能仍用到這個值。

在函式外定義的靜態變數——靜態全域性變數,該變數的作用域只能在定義該變數的檔案中,不能被其他檔案通過extern引用。

內部連結屬性

       靜態函式只能在宣告它的原始檔中使用。

問題2const關鍵字的作用?

答:

1宣告常變數,使得指定的變數不能被修改。

const int a = 5;/*a的值一直為5,不能被改變*/

const int b; b = 10;/*b的值被賦值為10後,不能被改變*/

const int *ptr; /*ptr為指向整型常量的指標,ptr的值可以修改,但不能修改其所指向的值*/

int *const ptr;/*ptr為指向整型的常量指標,ptr的值不能修改,但可以修改其所指向的值*/

const int *const ptr;/*ptr為指向整型常量的常量指標,ptr及其指向的值都不能修改*/

2修飾函式形參,使得形參在函式內不能被修改,表示輸入引數。

int fun(const int a);int fun(const char *str);

3修飾函式返回值,使得函式的返回值不能被修改。

const char *getstr(void);使用:const *str= getstr();

const int getint(void);  使用:const int a =getint();

問題3volatile關鍵字的作用?

答:

volatile指定的關鍵字可能被系統、硬體、程序/執行緒改變,強制編譯器每次從記憶體中取得該變數的值,而不是從被優化後的暫存器中讀取。例子:硬體時鐘;多執行緒中被多個任務共享的變數等。

問題4extern關鍵字的作用?

答:

1用於修飾變數或函式,表明該變數或函式都是在別的檔案中定義的,提示編譯器在其他檔案中尋找定義。

extern int a;

extern int *p;

extern int array[];

extern void fun(void);

其中,在函式的宣告帶有關鍵字extern,僅僅是暗示這個函式可能在別的原始檔中定義,沒有其他作用。如:

標頭檔案AA_MODULE.h中包含

extern int func(int a, int b);

原始檔A: A_MODULE.c

#include “A_MODULE.h”

int func(int a, int b)

{

         returna+b;

}

此時,展開標頭檔案A_MODULE.h後,為

extern int func(int a, int b);/*雖然暗示可能在別的原始檔中定義,但又在本檔案中定義,所以extern並沒有起到什麼作用,但也不會產生錯誤*/

int func(int a, int b)

{

         returna+b;

}

原始檔BB_MODULE.c中,

#include “A_MODULE.h”

int ret = func(10,5);/

展開標頭檔案A_MODULE.h後,為

extern int func(int a, int b);/*暗示在別的原始檔中定義,所以在下面使用func(5,10)時,在連結的時候到別的目標檔案中尋找定義*/

int ret = func(10,5);

用於extern “c

extern “c”的作用就是為了能夠正確實現C++程式碼呼叫其他C語言程式碼。加上extern "C"後,會指示編譯器這部分程式碼按C語言的編譯方式進行編譯,而不是C++的。

C++作為一種與C相容的語言,保留了一部分面向過程語言的特點,如可以定義不屬於任何類的全域性變數和函式,但C++畢竟是一種面向物件的語言,為了支援函式的過載,對函式的編譯方式與C的不同。例如,在C++中,對函式void fun(int,int)編譯後的名稱可能是_fun_int_int,而C中沒有過載機制,一般直接利用函式名來指定編譯後函式的名稱,如上面的函式編譯後的名稱可能是_fun

這樣問題就來了,如果在C++中呼叫的函式如上例中的fun(1,2)是用C語言在原始檔a_module.c中實現和編譯的,那麼函式fun在目標檔案a_module.obj中的函式名為_fun,而C++在原始檔b_module.cpp通過呼叫其對外提供的標頭檔案a_module.h引用後,呼叫fun,則直接以C++的編譯方式來編譯,使得fun編譯後在目標檔案b_module.obj的名稱為_fun_int_int,這樣在連結的時候,因為_fun_int_int的函式在目標檔案a_module.obj中不存在,導致了連結錯誤。

解決方法是讓b_module.cpp知道函式fun是用C語言實現和編譯了,在呼叫的時候,採用與C語言一樣的方式來編譯。該方法可以通過extern “C”來實現(具體用法見下面)。一般,在用C語言實現函式的時候,要考慮到這個函式可能會被C++程式呼叫,所以在設計標頭檔案時,應該這樣宣告標頭檔案:

/*標頭檔案a_module.h*/

/*標頭檔案被CPP檔案include時,CPP檔案中都含有該自定義的巨集__cplusplus*/

/*這樣通過extern “C”告訴C++編譯器,extern “C”{}裡包含的函式都用C的方式來編譯*/

#ifdef __cplusplus 

extern “C”

{

#endif

extern void fun(int a, int b);

#ifdef __cplusplus

}

#endif

extern "C"的使用方式

1. 可以是單一語句

   extern "C" doublesqrt(double);

2. 可以是複合語句相當於複合語句中的宣告都加了extern "C"

    extern "C"

    {

        double sqrt(double);

        int min(int, int);

    }

3.可以包含標頭檔案,相當於標頭檔案中的宣告都加了extern"C"

   extern "C"

   {

       #include <cmath>

  }

4. 不可以將extern"C" 新增在函式內部

5. 如果函式有多個宣告,可以都加extern"C", 也可以只出現在第一次宣告中,後面的宣告會接受第一個連結指示符的規則。

6. extern"C", 還有extern "FORTRAN" 等。

問題5sizeof關鍵字的作用?

答:

sizeof是在編譯階段處理,且不能被編譯為機器碼。sizeof的結果等於物件或型別所佔的記憶體位元組數。sizeof的返回值型別為size_t

變數:int a;  sizeof(a)4

指標:int *p;  sizeof(p)4

陣列:int b[10]; sizeof(b)為陣列的大小,4*10int c[0]; sizeof(c)等於0

結構體:struct (int a; char ch;)s1; sizeof(s1)與結構體位元組對齊有關。

注意:不能對結構體中的位域成員使用sizeof

sizeof(void)等於1

sizeof(void *)等於4

結構體

問題1:結構體的賦值?

答:

C語言中對結構體變數的賦值或者在初始化或者在定義後按欄位賦值。

方式1:初始化

struct tag

{

     chara;

   int b;

}x = {‘A’, 1};/*初始化*/

struct tag

{

char a;

int b;

};

struct tag x = {‘A’,1};/*在定義變數時初始化*/

GNU C中可使用另外一種方式:

struct tag

{

char a;

int b;

}x =

{

.a = ‘A’,

.b =1;

};

struct tag

{

char a;

int b;

};

struct tag x =

{

     .a= ‘A’,

   .b=1,

};

方式2:定義變數後按欄位賦值

struct tag

{

char a;

int b;

};

struct tag x;/*定義變數*/

x.a = ‘A’;/*按欄位賦值*/

x.b = 1; /*按欄位賦值*/

而當你使用初始化的方式來賦值時,如x = {‘A’,1};則出錯。

方式3:結構變數間的賦值

struct tag

{

     chara;

   int b;

};

struct tag x,y;

x.a=’A’;

x.b=1;

y = x;/*結構變數間直接賦值*/

問題2:結構體變數如何比較?

答:雖然結構體變數之間可以通過=直接賦值,但不同通過比較符如==來比較,因為比較符只作用於基本資料型別。這個時候,只能通過int memcmp(const void *s1, const void *s2, size_t n);來進行記憶體上的比較。

問題3:結構體位域

答:

位域是一個或多個位的欄位,不同長度的欄位(如宣告為unsigned int型別)儲存於一個或多個其所宣告型別的變數中(如整型變數中)。

位域的型別:可以是charshortint,多數使用int,使用時最好帶上signedunsigned

位域的特點:欄位可以不命名,如unsignedint :1;可用來填充;unsigned int :0; 0寬度用來強制在下一個整型(因此處是unsigned int型別)邊界上對齊。

位域的定義

struct st1

{

unsigned chara:7;/*欄位a佔用了一個位元組的7bit*/

unsigned charb:2;/*欄位b佔用了2bit*/

unsigned charc:7;/*欄位c佔用了7bit*/

}s1;

sizeof(s1)等於3。因為一個位域欄位必須儲存在其位域型別的一個單元所佔空間中,不能橫跨兩個該位域型別的單元。也就是說,當某個位域欄位正處於兩個該位域型別的單元中間時,只使用第二個單元,第一個單元剩餘的bit位置補(pad0

於是可知Sizeof(s2)等於3*sizeof(int)12

struct st2

{

unsigned inta:31;

unsigned intb:2;/*前一個整型變數只剩下1bit,容不下2bit,所以只能存放在下一個整型變數*/

unsigned int c:31;

}s2;

位域的好處

       1.有些資訊在儲存時,並不需要佔用一個完整的位元組, 而只需佔幾個或一個二進位制位。例如在存放一個開關量時,只有0兩種狀態,用一位二進位即可。這樣節省儲存空間,而且處理簡便。這樣就可以把幾個不同的物件用一個位元組的二進位制位域來表示。
        2.
可以很方便的利用位域把一個變數給按位分解。比如只需要4個大小在03的隨即數,就可以只rand()一次,然後每個位域取2個二進位制位即可,省時省空間。

位域的缺點

不同系統對位域的處理可能有不同的結果,如位段成員在記憶體中是從左向右分配的還是從右向左分配的,所以位域的使用不利於程式的可移植性。

問題4:結構體成員陣列大小為0

結構體陣列成員的大小為0GNU C的一個特性。好處是可以在結構體中分配不定長的大小。如

typedef struct st

{

        inta;

int b;

char c[0];

}st_t;

sizeof(st_t)等於8,即char c[0]的大小為0.

相關推薦

C語言試題2

1 預處理 問題1:什麼是預編譯?何時需要預編譯? 答: 預編譯又稱預處理,是整個編譯過程最先做的工作,即程式執行前的一些預處理工作。主要處理#開頭的指令。如拷貝#include包含的檔案程式碼、替換#define定義的巨集、條件編譯#if等。. 何時需要預編譯: 1、總是使用不經常改動的

經典C語言試題2:static關鍵字的用法?

C語言中static關鍵字的用法主要有以下三種:1、在函式體內,static變數的作用範圍為該函式體,該變數的記憶體只能被分配一次,下次呼叫時維持上次的值(即具有記憶功能)。2、在模組內的static全域性變數可以被模組內的所有函式訪問,但是不能被模組外的函式訪問(注:即使在

C語言試題分類->排序算法

OS sort 試題 時間復雜度 ups popup popu 使用 body 1.選擇排序。   每次將最小的數,與剩余數做比較。找到更小的,做交換。   時間復雜度:O(n2)   空間復雜度:O(1)   優缺點:耗時但內存空間使用小。 void selectSor

C語言試題分類->回調

指向 name 傳輸 join 接口 但是 PE AS 一個數 本文主要講解如果實現回調,特別是在封裝接口的時候,回調顯得特別重要,我們首先假設有兩個程序員在寫代碼,A程序員寫底層驅動接口,B程序員寫上層應用程序,然而此時底層驅動接口A有一個數據d需要傳輸給B,此時有兩種方

智郵普創c語言試題 ---- 字母概率

arr apple void != stdio.h app words 遊戲 包含 題目描述 小明最近對概率問題很感興趣。一天,小明和小紅一起玩一個概率遊戲,首先小明給出一個字母和一個單詞,然後由小紅計算這個字母在這個單詞中出現的概率。字母不區分大小寫。 例如,給定的字母是

C語言試題---指標篇(三)

版本宣告:本文轉載於公眾號TeachPlus C語言面試題---指標篇(三) 了解了記憶體空間,接下來我們就一起看一下指標自身用法的一些題目,先來看這樣一道題目: 分析下面程式碼:` # include <stdio.h> # include

C語言試題---指標篇(一)

版本宣告:本文轉載於公眾號TeachPlus 指標的使用,一直是c語言面試題中必考的部分, 因為指標本身使用的複雜性與普適性,所以考點非常多,而且也可以與其他知識相互結合, 因此我們將會使用五篇專題的篇幅來介紹指標。分析下面的程式,指出程式中的錯誤:

C語言試題---指標篇(二)

# include <stdio.h># include <stdlib.h># include <string.h>void getMemory( char **p , int num){ *p = malloc(num);} int main() {

100道c語言試題

題目來源: 1、中興、華為、慧通、英華達、微軟亞洲技術中心等中 外企業面試題目; 2、C 語言面試寶典(林銳《高質量程式設計第三版》)。 說明: 1、部分C 語言面試題中可能會參雜部分和C++ 相關的知 識,為了保持題目的靈活性故保留,但選題最終還是 會以C

C語言試題大彙總 (影象處理方向)

1、區域性變數能否和全域性變數重名?    答:能,區域性會遮蔽全域性。要用全域性變數,需要使用"::" ;區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同名的區域性變數,比如在兩個迴圈體內都定義一個同名的

C語言試題

關於“一年有多少秒”的巨集定義 網上關於這個問題的答案都是(365*24*60*60)UL,是錯誤的。 正解:數字和型別是一個整體,()是外人。 #include <stdio.h> #define SECONDS_PER_YEAR (3

9道常見C語言試題

1、區域性變數能否和全域性變數重名?      答:能,區域性會遮蔽全域性。要用全域性變數,需要使用"::" ;區域性變數可以與全域性變數同名,在函式內引用這個變數時,會用到同名的區域性變數,而不會用到全域性變數。對於有些編譯器而言,在同一個函式內可以定義多個同

12個有趣的C語言試題(中英文對照)

In this article, we will discuss some interesting problems on C language that can help students to brush up their C programming skills

C語言試題 4 (查詢整數陣列中第二大的數)

題目:寫一個函式找出一個整數陣列中,第二大的數。【Mirosoft】 PS:1、” 66,66,66,66,66 ”,則沒有第二大數。 2、” 99,99,88,86,68,66 ”,則最大數是88。 下面我先給出查詢最大數字的程式: int GetFirstMaxNumbe

c語言試題1

> 前處理器(Preprocessor) 1. 用預處理指令#define 宣告一個常數,用以表明1年中有多少秒(忽略閏年問題)     #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事情: 1).

2016 C語言試題——字串函式的實現

2016 C語言面試題——字串函式 前言:最近準備找工作了,所以需要做一些準備。先從基本的字串函式的實現開始。如果有發現什麼問題或有什麼疑惑,請及時評論。 strcat /************

C語言試題---指標篇(四)

解析:首先看最後一個問題, c  是第一個元素的地址, *c  是第一行元素的首地址,其實第一行元素的地址就是第一個元素的地址, **c  是提取第一個元素。為什麼 c  , *c  的值相等?c是陣列名,是一個二維指標,它的值就是陣列的首地址,也即第一行元素的首地址(等於 *c  ),也等於第一行第一個元素

經典C語言試題4:位元組對齊的作用

   一、什麼是位元組對齊?     在現代計算機中,記憶體空間都是按照字節(byte)劃分的。從理論上講對任何型別的變數的訪問可以從任何地址開始,但實際情況是,訪問特定型別的變數的時候經常在特定的記憶體地址訪問,這就需要各種型別的資料按照一定規則在空間上排列,而不是順序地一

嵌入式開發—C語言試題

前處理器(Preprocessor) 1. 用預處理指令#define 宣告一個常數,用以表明1年中有多少秒(忽略閏年問題) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事情: 1). #define 語

C語言試題——位域及大小端模式的理解

這裡涉及大小端的問題,我記為 “小高高,小弟弟(低低)”,就是: “小端模式,是指資料的高位儲存在記憶體的高地址中,資料的低位儲存在記憶體的低地址中” 這是記小端模式的,有點黃,不過好記!那麼大端模式就和這個相反嘍!!~~ 接下來就看一道面試題: #include<