首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言筆試面試題精選:從printf返回值到位運算陷阱全解析

     編輯:關於C語言

C語言筆試面試題精選:從printf返回值到位運算陷阱全解析

本文精選15道經典C語言筆試題,涵蓋標準庫返回值、宏展開機制、指針算術、運算符優先級、位運算提升、短路求值、sizeof特性等核心考點,附帶詳細解析與避坑指南。

題目一:printf與scanf返回值

int main() {
    int i = 43;
    int n = printf("%d\n", i);  // 輸出 "43\n"
    printf("%d\n", n);          // 輸出什麼?
    return 0;
}

答案:3(字符'4'、'3'、'\n'共3個)

規律:printf返回成功輸出字符數,錯誤返回負數;scanf返回成功賦值項目數,失敗返回EOF。

題目二:fgetc為何返回int而非char

原因:需區分有效字符0xFF(255)與EOF(-1)。若返回char,有符號時兩者均為-1,無符號時無法表示-1。

題目三:sizeof導致的循環陷阱

#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;
}

現象:無輸出

原因:sizeof返回size_t(無符號),比較時d被提升為無符號數,-1變為巨大正數,循環條件不成立。

修正:for(d = -1; d <= (int)TOTAL_ELEMENTS-2; d++)

題目四:宏字符串化與連接符

#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

printf("%s\n", h(f(1,2)));  // 輸出?
printf("%s\n", g(f(1,2)));  // 輸出?

答案:12 和 f(1,2)

解析:

  • g(f(1,2)):#直接字符串化參數,不展開內層宏 → "f(1,2)"
  • h(f(1,2)):h先展開參數 f(1,2)→12,再傳給g字符串化 → "12"

題目五:數組指針算術

int a[5]; // 假設地址 0xbfe2e100,32位系統
printf("%x\n", a);      // ?
printf("%x\n", a+1);    // ?
printf("%x\n", &a);     // ?
printf("%x\n", &a+1);   // ?

答案:

  • a:bfe2e100(數組首元素地址)
  • a+1:bfe2e104(+1个int,即+4字節)
  • &a:bfe2e100(數組地址值相同,但類型是int(*)[5])
  • &a+1:bfe2e114(+1個數組,即+5*4=20字節=0x14)

題目六:運算符優先級陷阱

int a = 2;
if(a & 1 == 0)  // 實際解析為 a & (1==0) 即 a & 0
    printf("a & 1 == 0");
else
    printf("a & 1 != 0");  // 輸出此行

優先級:==/!= > & > ^ > | > && > ||

題目七:短路求值與副作用

int i = 6;
if( ((++i < 7) && (i++/6)) || (++i <= 9) );
printf("%d\n", i);  // 輸出 8

過程:++i→7,7<7為假,&&短路跳過i++/6,||繼續評估++i<=9(i變8),最終i=8。

題目八:sizeof不計算表達式副作用

int i = 1;
sizeof(i++);
printf("%d\n", i);  // 輸出 1(i未增)

原因:sizeof編譯期求值,僅根據類型計算大小,不生成計算代碼。

題目九:移位優先級導致乘5錯誤

t = a<<2 + a;  // 實際為 a << (2+a),非 (a<<2)+a
// 修正:t = (a<<2) + a;

優先級:+ > <<

題目十:位運算整型提升

unsigned char c = 0xfc;
unsigned int i = ~c;
printf("%x\n", i);  // 輸出 0xffffff03,非 0x03

原因:c先提升為int(0x000000fc),再取反得0xffffff03。若c為char(有符號),提升為0xfffffffc,取反得0x03。

題目十一:無符號字符循環陷阱

#define MAX 255
unsigned char A[MAX], i;
for(i = 0; i <= MAX; i++)  // i最大255,i++後變0,無限循環
    A[i] = i;

題目十二:無分支求最大/最小值

max = ((a+b) + abs(a-b)) / 2;
min = ((a+b) - abs(a-b)) / 2;

題目十三:無比較運算符求最大值宏

#define MAX(a,b) ((((a)-(b)) & (1<<31)) ? (b) : (a))  // 32位系統

利用符號位判斷a-b正負。

題目十四:結構體成員偏移量宏

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

利用空指針解引用計算偏移(編譯期常量,不產生實際訪問)。

題目十五:求不小於x的最小2的冪

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後的所有位置1,再+1得到下一個2的冪。

附錄:常用位操作速查

// 設置bit5為1:  x |= (1<<5);
// 清除bit5為0:  x &= ~(1<<5);
// 測試bit5是否1: (x & (1<<5)) != 0
// 判斷偶數:     (num & 1) == 0

volatile關鍵字深度解析

作用:告訴編譯器「此變量可能意外改變」,禁止優化器缓存寄存器值,強制每次從內存讀取。

典型場景:

  1. 硬件寄存器(狀態寄存器、數據口)
  2. 中斷服務程序訪問的非自動變量
  3. 多線程共享變量(配合原子操作/鎖使用)

經典失效案例:線程A在循環中檢查寄存器中緩存的flag,線程B修改內存中flag,A永遠看不到變化 → 死循環。加volatile強制每次讀內存解決。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved