程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 幾道C筆試題

幾道C筆試題

編輯:關於C語言

幾道C筆試題


Q:printf和scanf的返回值是什麼?

int main()  
{  
    int i = 43;  
    int n = printf("%d\n",i);
    printf("%d\n",n);     
    return 0;
} 

A:printf函數返回3,因為其輸出了'4', '3', '\n' 三個字符。
printf返回的是成功輸出到STDOUT的字符數。如果發生錯誤,返回一個負數。
scanf返回的是成功賦值的變量個數,如果發生錯誤,返回EOF

Q:既然fgetc是接收輸入的字符,返回值用char或者unsigned char不就行了,為什麼用int呢?
A:這個主要是因為文件結束或者讀寫文件出錯的標志被規定成EOF,也就是-1導致的。unsigned char根本取不到-1這個值,而如果用char做返回值的話,它無法分辨0xFF字符和EOF,因為這兩個數值都被char認為是-1,所以它也不能作為返回值。

Q:此段程序希望輸出數組中的所有元素,但卻沒有得到想要的結果,是什麼產生歧義?

#include  
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0])) 
int array[] = {23,34,12,17,204,99,16}; 
int main() 
{
    int d;
    for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
        printf("%d\n",array[d+1]);
    return 0; 
} 

A:運行上面的程序,結果是什麼都沒有輸出,導致這個結果的原因是sizeof的返回值是一個unsinged int,為此在比較int d 和TOTAL_ELEMENTS兩個值都被轉換成了unsigned int來進行比較,這樣就導致-1被轉換成一個非常大的值,以至於for循環不滿足條件。因此,如果不能理解sizeof操作符返回的是一個unsigned int的話,就會產生類似如上的歧義。

Q:下面這段程序的輸出結果是:

#include  
#define f(a,b) a##b 
#define g(a)   #a 
#define h(a) g(a)   
int main() 
{
    printf("%s\n", h(f(1,2)));
    printf("%s\n", g(f(1,2)));
    return 0; 
} 

A:在C語言的宏中,#的功能是將其後面的宏參數進行字符串化操作(Stringfication)。而##被稱為連接符(concatenator),用來將兩個Token連接為一個Token。
看到這段程序你可能會認為,這兩個printf輸出的同一個結果,可是答案卻非如此,本題的輸出是12和f(1,2),為什麼會這樣呢?因為這是宏,宏的解開不象函數執行那樣由裡到外。#將右邊的參數做整體的字符串替換,即便是另一個宏,也不展開,所以,g(f(1,2))->"f(1,2)"。對於h(f(1,2)),由於h(a)是非#或##的普通宏,需要先宏展開其參數a,即展開f(1,2)為12,則h(a) 宏替換為h(12),進而宏替換為g(12), 進而宏替換為"12"。

Q:假如我們的a的地址是:0Xbfe2e100, 而且是32位機,那麼這個程序會輸出什麼?

#include 
int main()
{
    int a[5];
    printf("%x\n", a);
    printf("%x\n", a+1);
    printf("%x\n", &a);
    printf("%x\n", &a+1);
    return 0;
}

A:
第一條printf語句應該沒有問題,就是 bfe2e100。
第二條printf語句你可能會以為是bfe2e101。那就錯了,a+1,編譯器會編譯成 a+ 1*sizeof(int),int在32位下是4字節,所以是加4,也就是bfe2e104。
第三條printf語句可能是你最頭疼的,我們怎麼知道a的地址?我不知道嗎?可不就是bfe2e100。那豈不成了a==&a啦?這怎麼可能?自己存自己的?也許很多人會覺得指針和數組是一回事,那麼你就錯了。如果是 int *a,那麼沒有問題,因為a是指針,所以 &a 是指針的地址,a 和 &a不一樣。但是這是數組啊a[],所以&a其實是被編譯成了 &a[0]。
第四條printf語句就很自然了,就是bfe2e104。還是不對,因為是&a是數組,被看成int(*)[5],所以sizeof(a)是5,也就是5*sizeof(int),也就是bfe2e114。

Q:如下代碼為什麼結果始終不對?

#include 
int main()
{
    int a = 2;
    if(a & 1 == 0)
        printf("a & 1 == 0");
    else
        printf("a & 1 != 0");
    return 0;
}

為什麼輸出“a & 1 != 0”?
A:這是因為==的優先級高於表示位與運算符&.所以a & 1 == 0的實際代碼是a & (1 == 0),也就是a & 0, 當然結果不是預期了。(優先級:==和!= 高於 & 高於 ^ 高於 | 高於 && 高於 || )。優先級從高到低:算術運算符,位移運算符,關系運算符,位操作& ^ |

Q:如下代碼輸出什麼?

int main()
{
    int i = 6;
    if( ((++i < 7) && ( i++/6)) || (++i <= 9));
        printf("%d\n",i);
    return 0;
}

A:8。本題主要考的是&&和||的短路求值的問題。所為短路求值:對於(條件1 && 條件2),如果“條件1”是false,那“條件2”的表達式會被忽略了。對於(條件1 || 條件2),如果“條件1”為true,而“條件2”的表達式則被忽略了。

Q:sizeof後面可以跟表達式,下面的代碼,為什麼i++無效呢?

#include 
int main()
{
    int i = 1;
    sizeof(i++);
    printf("%d\n", i);
    return 0;
}

運行結果:1
A:正因為sizeof是編譯期求值的,所以如果它跟著表達式,那麼表達式是不被計算的,只是根本表達式的類型得到它占用的空間。

Q:下面的程序試圖使用“位操作”來完成“乘5”的操作,不過這個程序中有個BUG,你知道是什麼嗎?

#include 
#define PrintInt(expr) printf("%s : %d\n",#expr,(expr))
int FiveTimes(int a)
{
    int t;
    t = a<<2 + a;
    return t;
}
int main()
{
    int a = 1;
    PrintInt(FiveTimes(a));
    return 0;
}

A:本題的問題在於函數FiveTimes中的表達式“t = a<<2 + a;”,對於a<<2這個位操作,優先級要比加法要低,所以這個表達式就成了“t = a << (2+a)”,於是我們就得不到我們想要的值。該程序修正如下:“t = (a<<2) + a;”

Q:如下代碼關於位運算符的操作為何最終結果和預期不符?

#include 
int main()
{
    unsigned char c = 0xfc;
    unsigned int i = ~c;
    printf("%x\n",i);
    return 0;
}

運行結果:0xffffff03
按照上面的代碼,~c應該得到的是0x03, 那麼結果應該是0x03, 怎麼會是上面的結果呢?
A:這是因為位運算是被提升到整形運算的。上面的變量c是無符號字符型,在進行~位運算時,是首先提升為整形,即為0x000000fc, 然後取反得到0xffffff03, 所以i得到的數值是這個。同理,如果c是char類型,提升為整形時為0xfffffffc,再取反得到的就是0x03。其實變量被提升有很多地方,比如short計算時也會提升為int再繼續計算。

Q:下面這個程序執行後會有什麼錯誤或者效果:

#define MAX 255
int main()
{
    unsigned char A[MAX];
    unsigned chat i;
    for (i = 0; i <= MAX; i++)
        A[i] = i;
}

A:MAX=255,數組A的下標范圍為:0..MAX-1,下標越界。當i循環到255時,循環內執行: A[255]=255;這句本身沒有問題,但是返回for(i=0;i<=MAX;i++)語句時,由於unsigned char的取值范圍在[0,255],i++以後i又為0了,無限循環下去。
注意:char類型為一個字節,取值范圍是[-128,127],unsigned char取值范圍[0,255]

Q:有a和b兩個整型變量,不用“if”,“? :”,“switch”或者是其他判斷語句,如何得到大者和小者?
A:大者:((a+b)+abs(a-b))/2
小者:((a+b)-abs(a-b))/2

Q:請定義一個宏,比較兩個數a、b的大小,不能使用大於、小於、if語句
A:可以判斷兩個數相減後的符號,32位整數相減後的符號位:

#define MAX(a,b)  ((((a)-(b))&(1<<31))?(b):(a))

Q:定義一個宏,求一個結構體struct中某個變量相對於struct的偏移量

A:#define OFFSET(struct, member)  ((unsigned int)&((struct *)0)->member)

Q:求不小於x的最小的2的K次方的數:

int pow2_ceil(unsigned int x)
{
    x--;
    x |= x >> 1;
    x |= x >> 2;
    x |= x >> 4;
    x |= x >> 8;
    x |= x >> 16;
    x++;
    return x;
}

靈活的位操作可以有效地提高程序運行的效率:
1.設置x的bit5為1,其他位不變:x |= (1<<5);
2.設置x的bit5為0,其他位不變:x &= ~(1<<5);
3.判斷x的bit5是否為1,(x & (1<<5)) != 0 ? 1:0;
4.判斷一個數是不是偶數:(num & 1) == 0 ? 1:0;

關於C中volatile關鍵字的作用:一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器裡的備份。
下面是volatile變量的幾個例子:
1). 並行設備的硬件寄存器(如:狀態寄存器)
2). 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables,自動變量是auto或register變量)
3). 多線程應用中被幾個任務共享的變量:volatile 關鍵字告訴編譯器不要持有變量的臨時性拷貝。請看以下情形:A線程將變量復制入寄存器,然後進入循環,反復檢測寄存器的值是否滿足一定條件,它期待B線程改變變量的值。在此種情況下,當B線程改變了變量的值時,已改變的值對其在寄存器的值沒有影響。所以A線程進入死循環。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved