<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                以下這些題目是我曾遇到過的,覺得有深度的問題,對題目的解析絕大部分是本人的思考(引用的已注明出處),可能有不對的地方,希望大家不吝指正。 (PS:如果您對以下題目表示無壓力,只能說您對C有一定的理解,至于是否精通C,不能由此文判斷。)參考答案在文末。 1★先來個簡單的: ~~~ #include <stdio.h> int main(void) { int a[3][2] = { (0,1), (2,3), (4,5) } ; int *p ; p = a[0] ; printf(“%d”, p[0] ) ; } ~~~ 仔細看看花括號里面嵌套的是小括號,而不是花括號。即這花括號里嵌套了逗號表達式。(這考的是眼力^_^) 2★?int a[10]; 問下面哪些不可以表示 a[1] 的地址? A. a+sizeof(int) ? B. &a[0]+1 ? ?C. (int*)&a+1 ? ?D. (int*)((char*)&a+sizeof(int)) //Tecent某年實習生筆試題目 此題對于理解了指針與數組的同學來說,很easy。(關于數組和指針那點事,可瀏覽本博客, [點這里](http://blog.csdn.net/yang_yulei/article/details/8071047)) 3★下面的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; }//來源于酷殼網http://coolshell.cn/articles/945.html ~~~ 本例主要展示了一種另類的用法。下面的兩種用法是相同的: “hello”[2] 2["hello"] 如果你知道:a[i] 其實就是 *(a+i)也就是 *(i+a),所以如果寫成 i[a] 應該也不難理解了。 4★?32 位機上根據下面的代碼,問哪些說法是正確的?(多選題類型) ~~~ signed char a = 0xe0; unsigned int b = a; unsigned char c = a; ~~~ A. a>0 && c>0 為真 ? ? ? B. a == c 為真 ? ? ?C. b 的十六進制表示是:0xffffffe0 ? ? D. 上面都不對 //Tencent某年實習生筆試題目 此題深入地考察了C的類型轉換方式。(此為多選題類型,一般人不敢確定他的答案是正確的) A 錯:a 是負數,c 是正數,跟 0 比較要轉換到 int。 ? ? signed char a 其實也就是char a,其轉換到int負數還是負數(高位填充1)轉換后結果為0xFFFFFFE0 ? ? unsigned char c 也為0xE0,但其是正數(signed char轉unsigned char 底層位不變 只是改變了解釋規則) ? ? unsigned char 轉int,正數還是正數(高位填充0)轉換后結果為0x000000E0 B 錯:B錯?首先說 a 和 c 的二進制表示一模一樣,都是 0xe0,那么比較就不相等?!是的。 ? ? 一個char型和一個unsigned char比較,其中的類型如何轉換? ? ? C語言的整型提升規則:C的整型算數運算總是至少以缺省整型類型的精度來進行的。為了獲得這個精度,表達式中的字符型和短整型操作數在使用之前被轉換為普通整型。 ? ? 本博的早期文章:http://blog.csdn.net/yang_yulei/article/details/8068210 ? ? 所以,a == c中,a和c都要先轉換成int型,再比較。有A選項分析知,a轉int型為負數,b轉int型為正數,故它倆不等。 C 對:C對?C 怎么就對了?a 是一個 signed char,賦值給 unsigned int 的 b,前若干個字節不是補 0 嗎? ? ? 但實際情況是:首先 signed char 轉換為 int,然后 int 轉換成 unsigned int,所以最初是符號擴展,然后一個 int 賦值給了 unsigned int(其實還是整型提升規則) D 不解釋。 至于對這個問題的解釋,我認為(只是我認為,不是權威的解釋)是因為你使用的是32位的操作系統,我們說的操作系統的位數其實值的是CPU GPRs(General-Purpose Registers,通用寄存器)的數據寬度為32位,32位指令集就是運行32位數據的指令,也就是說處理器一次可以運行32bit數據。你傳遞參數的時候輸入指定的格式為%hd,但是壓棧的時候還是壓入了32bit的數據,只不過高位是0。要不然我們為什么經常會說c語言中字節對齊的問題? 5★?下面程序的輸出結果(32位小端機) ~~~ #include <stdio.h> int main() { long long a = 1, b = 2, c = 3; printf("%d %d %d\n", a, b, c); return 0; } //Tencent某年實習生筆試題目 ~~~ //以下是長篇大論 首先,sprintf/fprintf/printf/sscanf/fscanf/scanf等這一類的函數,它們的調用規則(calling conventions)是cdecl,cdecl調用規則的函數,所有參數從右到左依次入棧,這些參數由調用者清除,稱為手動清棧。被調用函數不會要求調用者傳遞多少參數,調用者傳遞過多或者過少的參數,甚至完全不同的參數都不會產生編譯階段的錯誤。函數參數的傳遞都是放在棧里面的,而且是從右邊的參數開始壓棧,printf()是不會對傳遞的參數進行類型檢查的,它只有一個format specification fields的字符串,而參數是不定長的,所以也沒辦法對傳遞的參數做類型檢查,也沒辦法對參數的個數進行檢查。所以了,壓棧的時候,參數列表里的所有參數都壓入棧中了,它不知道有多少個參數,所以它都壓棧。 那么問題來了:編譯器是怎么去定義壓棧的行為的?是先把這longlong類型轉換為int型再壓棧么?還是直接壓棧? 在32位機器上,64位的整數被拆分為兩個32位整數,printf會把64位的按照兩個32的參數來處理。此時printf會認為實際的參數為6個,而不是3個。 c,b,a壓入之后,在最低的12字節處是a和b,a占2*4個bytes,b占1*4個byte。b先壓入棧,a后壓入棧。但是為什么a的布局是這樣的?因為這是little endian,即每個數字的高字節在高地址,低字節在低地址。而棧的內存生長方向是從大到小的,也就是棧底是高地址,棧頂是低地址,所以a的低字節在低地址。(有條件的同學可以在big endian的機器上驗證一下) 那么輸出的時候,format specification fields字符串其匹配棧里面的內容,首先一個%d取出4個bytes出來輸出,然后后面又有一個%d再取出4個bytes出來打印。所以結果就是這樣了。也就是說剛開始壓入棧的b的值在輸出的時候根本都沒有用到。 總結: printf在壓棧時,對于長度小于32位的參數,自動擴展成32位(由CPU的位數決定的)。 故在根據格式串解釋時,對于%c %hd這樣的小于32位數據的格式串,系統也會自動提取32位數據解釋,而不會提取8位或16位來解釋。(因為你把人家壓入的時候就規定了擴展成32位嘛) 至于浮點參數壓棧的規則:float(4 字節)類型擴展成double(8 字節)入棧。所以在輸入時,需要區分float(%f)與double(%lf),而在輸出時,用%f即可。printf函數將按照double型的規則對壓入堆棧的float(已擴展成double)和double型數據進行輸出。 至于longlong參數的規則:在32位機上,64位整數被拆分為兩個32位整數壓棧,在64位機上不存在這個問題,64位機上本題輸出1,2,3 PS: 關于longlong型的輸出:和平臺和編譯器有關 在**windows下需要用__int64配合%I64d**。而在**UNIX、Linux中必須使用標準C規定的long long配合%lld。** unsigned __int64b= 9223372036854775808ll printf("%I64u",b); 6★下面這段代碼會掛么?會掛在哪一行? ~~~ #include <stdio.h> struct str{ int len; char s[0]; }; struct foo { struct str *a; }; int main(int argc, char**argv) { struct foo f={0}; if (f.a->s) { printf( f.a->s); } return 0; } ~~~ //詳細分析請見本博客,[點這里](http://blog.csdn.net/yang_yulei/article/details/23395315)。 7★請問下面的程序的輸出值是什么? ~~~ #include <stdio.h> #include <stdlib.h> #define SIZEOF(arr)(sizeof(arr)/sizeof(arr[0])) #define PrintInt(expr)printf("%s:%d\n",#expr,(expr)) int main() { /* The powers of 10*/ int pot[] = { 0001, 0010, 0100, 1000 }; int i; for(i=0; i<SIZEOF(pot); i++) PrintInt(pot[i]); return 0; }//來源于酷殼網http://coolshell.cn/articles/945.html ~~~ 參考答案:好吧,如果你對于PrintInt這個宏有問題的話,你可以百度一下。不過,本例的問題不在這里,其實很簡單了,以C/C++中,以0開頭的數字都是八進制的。 8★請問下面的程序的輸出值是什么? ~~~ #include <stdio.h> int main(void) { char a[1000] ; int i ; for(i=0; i<1000; i++) { a[i]= -1-i ; } printf(“%d”,strlen(a)) ; return 0 ; } ~~~ 按照負數補碼規則,可知-1的補碼為0xff,當i值為127時,a[127]的值為-128,此時右邊整型轉換后,正好是左邊char型能夠表示的最小負數。當i繼續增加,右邊為-129,對應的十六進制數為0xffffff7f 而char只有8位,故轉換時高位被丟棄 左邊得到0x7f。當i繼續增加到255時,-256的低8位為0。然后當i增加到256時,-257的低8位為0xff 如此又開始一輪的循環。 從上面分析可知:a[0]到a[254]里面的值都不為0,而a[255]的值為0. 故strlen(a)為255 【char默認是有符號的,其表示的值的范圍為[-128,127]】 9★在X86系統下,輸出的值為多少? ~~~ #include <stdio.h> int main(void) { int a[5]={1,2,3,4,5} ; int* ptr1 =(int *)(&a+1) ; int* ptr2 =(int *)((int)a+1) ; printf(“%x,%x”,ptr1[-1], *ptr2) ; return 0 ; } ~~~ 若對于指針ptr1和ptr2具體指向不明白的,[請點擊這里瀏覽。。](http://blog.csdn.net/yang_yulei/article/details/8071068) 對于ptr[-1]的值為5,沒什么好說的了。 此題主要涉及的是大小端的問題,intel機器一般是小端模式,即:例如對整數來說,內存中的低地址字節存儲整型的低地址部分,內存中的高地址字節存整型的高地址部分。(與我們平時的書寫順序相反) a[0] a[1]在內存中的存儲為:(地址從小到大增長)0x1000 0000? 0x2000 0000 ptr2指向a[0]的第二個字節處,且它為int型指針,故提取從a[0]的第二個字節開始的后面4個字節。在內存中即為0x10**000000?0x20**00 0000(陰影部分) 打印來為0x2000000 10★ ~~~ (*(void(*)( ))0 )( ) 這是什么? ~~~ //可參考:[請點擊這里瀏覽函數指針部分](http://blog.csdn.net/yang_yulei/article/details/8071068) 這個是《C陷阱與缺陷》中的一個例子。 從內層到外層分析: 1,void(*)()這是一個函數指針。 這個函數沒有返回值也沒有參數 2,void(*)()0這是將整型0強制轉換為函數指針類型。(即:0號地址處開始存儲著一段函數) 3,(*(void(*)( ))0 ) 取出0號地址處的函數 4,(*(void(*)( ))0 )( ) 調用0號地址處的函數。 【由此可見 指針和強制類型轉換聯手雙劍合璧威力無窮! 可以實現匯編級的操作】 **【相信程序員,不阻止程序員做他們想做的事】** 11★請問下面的程序的輸出值是什么? ~~~ #include <stdio.h> int main() { int a[5][5] ; int (*p)[4] ; p=a ; printf("%d", &p[4][2]-&a[4][2]) ; return 0 ; } ~~~ [詳細分析請點擊](http://blog.csdn.net/yang_yulei/article/details/8071068) 12★ ~~~ struct S { char c ; int i[2]; double v ; } ; ~~~ 在windows系統下成員i的偏移量是多少?在Linux系統下i的偏移量是多少? [//請點擊這里參考](http://blog.csdn.net/yang_yulei/article/details/8072567) 13★下面代碼中有BUG,請找出: ~~~ int tadd_ok(int x, int y) //判斷加法溢出 { int sum = x+y ; return (sum-x == y) && (sum-y == x) ; } int tsub_ok(int x, int y) //判斷減法溢出 { return tadd_ok(x, -y) ; } //此題來源于等重量黃金價值的書——《深入理解計算機系統》 ~~~ 有兩個BUG: 1,tadd_ok判斷加法溢出時,無論是否溢出,(x+y)-x都==y,若溢出結果sum再減y 再溢出得x。正確實現應為:分兩種情況——正數運算是否溢出(即兩正數相加為負數),負數運算是否溢出(即兩負數相加為正數)。有兩種情況之一者即判斷溢出。 2,return tadd_ok(x, -y) ;當y為TMIN即int型所能表示的最小值,由于補碼范圍的不對稱性,int的最小值無對應的正值,故y取TMIN時,對其取反會發生溢出,溢出的結果還是TMIN。 這樣就導致判斷結果錯誤。 14★ ~~~ 編寫一些代碼,確定一個變量是有符號數還是無符號數: ~~~ //來源于《C專家編程》 參考答案: 無符號數的本質特征是它永遠不會是負的。 用宏定義的形式:#define ISUNSIGNED (type)? ( (type)0 –1> 0 ) //也有其它方法實現,不過個人認為這種方法最簡潔。 15★ 再來一發關于復雜指針聲明的,這是C中的難點: 寫出變量abc的核心是什么,并用多個typedef改寫下面的聲明式 ~~~ int *(*(*(*abc) ( ) ) [6]) ( ) ; ~~~ 解析: abc是一個函數指針,這類函數接收0個參數,返回一個指針,這個指針指向一個具有6個元素的數組,數組里的每個元素是函數指針,這類函數接收0個參數,返回值為int* 類型。abc的定義同下:? typedef int* (*type1)(); typedef type1 (*type2)[6]; typedef type2 (*type3)();? type3 abc; 【從內到外解讀聲明,從外到內typedef】 **關于變量的復雜聲明:** 從外到內,層層剝開,先找核心,再向右看。(個人總結的,若有不妥請指正) 找到核心變量后,從右向左讀。 * 讀作”指向…的指針” [] 讀作”…的數組” () 讀作”返回…的函數” 簡單的例子: **int *f() ; ? ? ? ? ? ? // f: 返回指向int型的指針** 步驟: 1)找標識符f:讀作”f是…” 2)向右看,發現”()”讀作”f是返回…的函數” 3)向右看沒有什么,向左看,發現*,讀作”f是返回指向…的指針的函數” 4)繼續向左看,發現int,讀作”f是返回指向int型的指針的函數” **int (*pf)() ; ? ? ? ? ?// pf是一個指針——指向返回值為int型的函數** 1)標識符pf,讀作“pf是…” 2)向右看,發現),向左看,發現\*,讀作 “pf是指向…的指針” 3)向右看,發現”()”,讀作“pf是指向返回…的函數的指針” 4)向右看,沒有,向左看發現int,讀作”pf是指向返回int型的函數的指針 **部分答案:** 1題、答案應該是1. 2題、答案為A。 3題、本例是合法的,輸出如下: Hello! how is this? super That is C ! 4題、略 5題、結果為:1,0,2 6題、略 7題、本例的輸出會是:1,8,64,1000 8題、答案是:255 8題、答案:5,2000000 9題、略 10題、略 11題、答案-4 12題、略 13題、略
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看