1. 程式人生 > >C語言面試常考內容

C語言面試常考內容

static

下面是中興通訊2012校招筆試題的一道問答題:

  1. static全域性變數與普通的全域性變數有什麼區別 ?   全域性變數(外部變數)的說明之前再冠以static 就構成了靜態的全域性變數。   全域性變數本身就是靜態儲存方式, 靜態全域性變數當然也是靜態儲存方式。 這兩者在儲存方式上並無不同。   這兩者的區別在於非靜態全域性變數的作用域是整個源程式, 當一個源程式由多個原始檔組成時,非靜態的全域性變數在各個原始檔中都是有效的。 而靜態全域性變數則限制了其作用域, 即只在定義該變數的原始檔內有效, 在同一源程式的其它原始檔中不能使用它。由於靜態全域性變數的作用域侷限於一個原始檔內,只能為該原始檔內的函式公用,因此可以避免在其它原始檔中引起錯誤。

static全域性變數只初使化一次,防止在其他檔案單元中被引用;  

2、static區域性變數和普通區域性變數有什麼區別 ?

  把區域性變數改變為靜態變數後是改變了它的儲存方式即改變了它的生存期。把全域性變數改變為靜態變數後是改變了它的作用域,限制了它的使用範圍。

  static區域性變數只被初始化一次,下一次依據上一次結果值;  

3、 static函式與普通函式有什麼區別?

   static函式與普通函式作用域不同,僅在本檔案。只在當前原始檔中使用的函式應該說明為內部函式(static修飾的函式),內部函式應該在當前原始檔中說明和定義。對於可在當前原始檔以外使用的函式,應該在一個頭檔案中說明,要使用這些函式的原始檔要包含這個標頭檔案.

 static函式與普通函式最主要區別是static函式在記憶體中只有一份,普通靜態函式在每個被呼叫中維持一份拷貝程式的區域性變數存在於(堆疊)中,全域性變數存在於(靜態區)中,動態申請資料存在於(堆)。  static函式在記憶體中只有一份,普通函式在每個被呼叫中維持一份拷貝 C語言中的static: 1、表示變數是靜態儲存變數,即變數存放在靜態儲存區. 2,表示該變數是內部連線,(這種情況是指該變數不在任何{}之內,就象全域性變數那樣,這時候加上static) ,也就是說在其它的.cpp檔案中,該變數是不可見的(你不能用).

當static加在函式前面的時候 表示該函式是內部連線,只在本檔案中有效,別的檔案中不能用該函式. 不加static的函式預設為是全域性的。 也就是說在其他的.cpp中只要宣告一下這個函式,才可以使用它。 C++中static

檔案內的,匿名名稱空間內,定義的變數,相當於檔案靜態變數。作用域為檔案,生命週期是程式生命期。 類內部定義的靜態變數,作用域為類,生命週期是程式生命期。可以使用的區域是類。 和函式不同,函式內部定義的靜態變數;不可用在其他地方,只能通過函式呼叫訪問。類內部定義的靜態變數,可以直接在類外部,通過類名引用。 關於static可參閱: https://www.cnblogs.com/felix-kun/p/5404058.html

const:具有常屬性

1、const修飾成員變數 (1)關於引用時候的const const可以修飾const變數、非const變數,而非const變數不能修飾const變數,只能修飾非const變數。

int a=10;//非const變數
const int b=20;//const變數

const int& c=a;//const修飾非const變數
const int& d=b;//const修飾const變數

int& e=a;//非const修飾非const
int& f=b;//非const不能修飾const,這是錯誤寫法

const變數說明變數只讀,而非const變數來引用就改變了它的只讀屬性,顯然不可以。 (2)const修飾指標變數

int a=10;//非const data
const int b=a;//const變數

int * a3 = &a1;             //非const data,非const pointer
const int * a4 = &a1;       //const data,non-const pointer
int * const a5 = &a1;       //non-const data,const pointer
int const * const a6 = &a1;   //const data,const pointer
const int * const a7 = &a1;   //const data,const pointer

const修飾指標變數時:   1)只有一個const,如果const位於*左側,表示指標所指資料是常量,不能通過解引用修改該資料;指標本身是變數,可以指向其他的記憶體單元。   2)只有一個const,如果const位於*右側,表示指標本身是常量,不能指向其他記憶體地址;指標所指的資料可以通過解引用修改。   3)兩個const,*左右各一個,表示指標和指標所指資料都不能修改(3)const修飾函式引數:表示被修飾的函式引數在函式體中不能被修改。

2、const修飾函式返回值 const修飾函式返回值相對於值傳遞沒有意義,而對於指標傳遞來說

const int * mallocA(){  ///const data,non-const pointer
    int *a=new int(2);
    return a;
}

int main()
{
    const int *a = mallocA();
    ///int *b = mallocA();  ///編譯錯誤
    return 0;
}

如果返回const data,non-const pointer,返回值也必須賦給const data,non-const pointer。因為指標指向的資料是常量不能修改。 3、const修飾成員函式 (1)const修飾的成員函式不能修改任何的成員變數(mutable修飾的變數除外) (2)const修飾的成員函式不能呼叫非const成員函式,因為非const成員函式可能會修改const修飾的成員函式的成員變數 const還可參閱:https://www.cnblogs.com/xudong-bupt/p/3509567.html

巨集定義和巨集函式

1、這是一個常見的兩個數比較大小的巨集函式:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

#define Max(a,b) (((a)>(b))?(a):(b))
using namespace std;

int main()
{
    int x = 3;
    int y = 7;
    cout << "Max" << Max(x, y) << endl;

    system("pause");
    return 0;
}

2、在巨集定義中 使用#表示,把一個巨集引數替換成對應的字串。 例如上式中的Max(a,b)被替換成了(((a)>(b))?(a):(b)),從而實現了兩個數的比較。 使用##,起到將符號左右兩部分連線的作用。

#include<iostream>
#define Test(Test1,Test2)\
do{\
    std::cout << #Test1"and " ##Test2<< std::endl;\
} while (0);
int main()
{
    Test("I am the head", "I am the tail");
    system("pause");
    return 0;
}

結果如下:

"I am the head"and I am the tail
a、使用巨集一般要求程式碼短小,巨集替換髮生在預處理階段,
而函式存在棧幀壓棧等操作,因此巨集比函式高效(時間方面)。
b、巨集是無型別的,可以適用於任意型別。

巨集的缺點:

a、巨集要求程式碼短小,否則每次呼叫巨集都會展開,會造成空間冗餘。
b、巨集是沒法除錯的。
c、巨集由於型別無關,也就不夠嚴謹。
d、巨集可能會帶來運算子優先順序的問題,導致程容易出現錯。

這裡寫圖片描述 4、帶副作用的巨集函式引數

x++;//帶副作用
x+1;//不帶副作用
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>

#define Max(a,b) (((a)>(b))?(a):(b))
using namespace std;

int main()
{
    int x = 3;
    int y = 7;
    int z = Max(x++, y++);
    cout << "x="<<x << ' '<<"y=" << y <<' '\
    <<"z="<< z << endl;

    system("pause");
    return 0;
}
x=4 y=9 z=8

經過巨集替換——>(((x++)>(y++))?(x++):(y++))(4>8)?顯然不成立,取(y++),先將y賦值給z,然後再y=y+1 5、巨集可以在命令列定義

#include <stdio.h>
int main()
{
int array [ARRAY_SIZE];
int i = 0;
for(i = 0; i< ARRAY_SIZE; i ++)
{
array[i] = i;
}
for(i = 0; i< ARRAY_SIZE; i ++)
{
printf("%d " ,array[i]);
}
printf("\n" );
return 0;
}
//編譯指令:
gcc -DARRAY_SIZE=10 programe.

可以實現一個根據實際需要去設定陣列容量的陣列。 6條件編譯

記憶體對齊

陣列和指標

棧幀&傳值&傳地址&傳引用