其實已經看了很多很好的帖子,但是隻看帖子不能達到系統的認識/最新的認識,一定要看官方標準/大牛著作!
值得深究的有:4
1、下面的程序並不見得會輸出 hello-std-out 在Qt 5.2 Plain C Project下測試,每次都會輸出hello-std-out。
參考答案:stdout是塊設備,stderr則不是。對於塊設備,只有遇到下面幾種情況下才會被輸入,1)遇到回車,2)緩衝區滿,3)flush被調用。#include <stdio.h> #include <unistd.h> int main(void) { while(1) { fprintf(stderr,"hello-std-err "); fprintf(stdout,"hello-std-out "); sleep(1); } return 0; }
2、下面的程序看起來是正常的,使用了一個逗號表達式來做初始化。
參考答案:這個程序會得到編譯出錯(語法出錯),逗號表達式是沒錯。但是在初始化和變量聲明時,逗號並不是逗號表達式的意義。這點要區分,要修改上面這個程序,需要加上括號: int a = (1,2);#include <stdio.h> int main() { int a = 1,2; printf("a : %d\n",a); return 0; }
3、下面的程序會有什麼樣的輸出
運行結果:#include <stdio.h> int main() { int i=43; printf("%d\n",printf("%d",printf("%d",i))); return 0; }
參考答案:printf返回值是輸出的字符個數。
4、下面的程序會輸出什麼 這個值得重點分析,涉及到計算機內部存儲數據的格式,需要補補計算機系統結構了
#include <stdio.h> int main() { float a = 12.5; printf("%d\n", a); printf("%d\n", (int)a); printf("%d\n", *(int *)&a); return 0; }
運行結果:
參考答案:浮點數是4個字節,12.5f 轉成
二進制是:01000001010010000000000000000000,
十六進制是:0x41480000,
十進制 是:1095237632。
所以,第二和第三個輸出相信大家也知道是爲什麼了。而對於第一個,爲什麼會輸出0,我們需要了解一下float和double 的內存佈局,如下:
float: 1位符號位(s)、8位指數(e),23位尾數(m,共32位)
double: 1位符號位(s)、11位指數(e),52位尾數(m,共64位)然後,我們還需要了解一下printf由於類型不匹配,所以,會把float直接轉成double,注意,12.5的float和double的內存二進制完全不一樣。別忘了在x86芯片下使用是的反字節序,高位字節和低位字位要反過來。所以:
float版:0x41480000 (在內存中是:00 00 48 41)
double版:0x4029000000000000 (在內存中是:00 00 00 00 00 00 29 40)
而我們的%d要求是一個4字節的int,對於double的內存佈局,我們可以看到前四個字節是00,所以輸出自然是0了。 這個示例向我們說明printf並不是類型安全的,這就是爲什麼C++要引如cout的原因了。
5、下面,我們再來看一個交叉編譯的事情,下面的兩個文件可以編譯通過嗎?如果可以通過,結果是什麼
file1.c
file2.cint arr[80];
Visual Studio 2010 編譯錯誤提示:extern int *arr; int main() { arr[1] = 100; printf("%d\n", arr[1]); return 0; }
參考答案:一個指向數組的指針,並不等於一個數組。修改:extern int arr[]。(參考:ISO C語言 6.5.4.2 節)
6、是關於switch語句的,參見博文:switch的三個注意點
7、請問下面的程序會有什麼潛在的危險
記得剛學C語言時,字符串以‘\0’結束這個知識點被我忽略了很久,也因此讓我有點時間遇到類似問題,痛苦的要死。#include <stdio.h> int main() { char str[80]; printf("Enter the string:"); scanf("%s",str); printf("You entered:%s\n",str); return 0; }
參考答案:本題很簡單了。這個程序的潛在問題是,如果用戶輸入了超過80個長度的字符,那麼就會有數組越界的問題了,你的程序很有可以及會crash了。
8、請問下面的程序輸出什麼
運行結果:Tested by Qt Plain C Project#include <stdio.h> int main() { int i; i = 10; printf("i : %d\n",i); printf("sizeof(i++) is: %d\n",sizeof(i++)); printf("i : %d\n",i); return 0; }
參考分析:sizeof不是一個函 數,是一個操作符。求(i++)的類型的size,這是一件可以在程序運行前(編譯時)完全的事情,所以,sizeof(i++)直接就被4給取代了,在運行時也就不會有了i++這個表達式。
9、請問下面的程序的輸出值是什麼#include <stdio.h> #include <stdlib.h> #define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0])) // 我愚昧了,以前從來沒想過用這種方式計算定義時未指定 // 數組長度的數字的長度 #define PrintInt(expr) printf("%s:%d\n",#expr,(expr)) // #expr以字符形式輸出expr int main() { int pot[] = { 0001, 0010, 0100, 1000 }; int i; for(i=0;i<SIZEOF(pot);i++) { PrintInt(pot[i]); } return 0; }
運行結果:
參考答案:其實很簡單,在C/C++中,以0開頭的數字都是八進制的。
10、下面的輸出是什麼
運行結果:#include <stdio.h> int main() { int i = 6; if( ((++i < 7) && ( i++/6)) || (++i <= 9)); printf("%d\n",i); return 0; }
參考答案:本題主要考的是&&和||的短路求值的問題。
11、下面的C程序是合法的嗎?如果是,那麼輸出是什麼
運行結果:#include <stdio.h> int main() { int a=3, b = 5; printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]); printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"],2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]); return 0; }
參考答案:下面的兩種用法是相同的: "hello"[2], 2["hello"]。如果你知道:a[i] 其實就是 *(a+i)也就是 *(i+a),所以如果寫成 i[a] 應該也不難理解了。
12、請問下面的程序輸出什麼
運行結果-1:#include <stdio.h> int main() { char dummy[80]; printf("Enter a string:\n"); scanf("%[^r]",dummy); printf("%s\n",dummy); return 0; }
運行結果-2:
參考答案:"%[^r]",當且僅當遇到字符r才結束輸入,而且r不被指針接收。
13、下面的程序試圖使用“位操作”來完成“乘5”的操作
int FiveTimes(int a) { int t; t = a<<2 + a; // 因爲<<的優先級低於+,所以正確的是:t = (a<<2) + a; return t; }