C語言學習趣事_經典面試題系列_2

來源:互聯網
上載者:User

      最近老感覺自己的身體一天不如一天,老是丟三落四的, 哎,歲月啊..................

      在此給還在被中國教育的童鞋們一個建議.............在學校的時候還是小玩玩遊戲,小談談一些海闊天空的事,當你工作後,你會發現你

不但沒有時間這個本錢了, 同時連身體這個本錢也沒有了..........

       上次說了一些有意思的面試題, 今天我們結著看看一些關於指標和sizeof的面試題:

下面是我看到的一些面試題

5、簡述
        char * const p;
        char const *p;
        const  char *p;
   之間的區別。

    首先討論:
               char  * const p;   這裡可以知道const修飾是指標變數p; 因此指標p的指向不能改變,這樣的變數
          定義必須首先初始化,否則將不能編譯通過。但是p指向的變數的儲存內容可以改變。
               Exp:
                      char chTest1;
                      char chTest2;
                      char  * const p=&chTest1;
                      // p=&chTest2;   這個地方是錯誤的,不能這樣賦值
                      *p=‘c’;
                      chTest1=‘b’;
    接下來討論:
               char const *p;     這裡可以知道const修飾的是*p; 因此可以知道不能通過*p指向來改變變數的值; 但是
    指標p的指向可以改變,而且可以通過原變數進行改變值。
              Exp:
                     char chTest1;
                     char chTest2;
                     char const *p=&chTest1;
                     p=&chTest2;
                     chTest=‘a’;
             這裡可以知道: 1)p的指向可以改變
                           2)不能通過*p= 某個值進行賦值
                           3)指標指向的變數的值自己可以改變。
   
    最後討論:
             const char  *p=&chTest1;  這裡可以知道const修飾的是*p; 因此這個與char const *p;具有相同的效果。
           Exp:      
               char chTest1;
               char chTest2;
               const char  *p=&chTest1;
               p=&chTest2;
               chTest1='a';
               // *p='a';  這個地方錯誤, 不能這樣修改值。

   總結:
          修飾符僅對其修飾的對象起作用,對別的變數不起作用。

6、以下代碼中的兩個sizeof用法有問題嗎?
               void UpperCase( char str[] ) // 將 str 中的小寫字母轉換成大寫字母
           {   
                for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )      
                   if( 'a' <=str[i] && str[i] <='z' )           
                             str[i] -= ('a'-'A' );
             }
            char str[] = "aBcDe";
            cout < < "str字元長度為: " < < sizeof(str)/sizeof(str[0]) < < endl;
            UpperCase( str );
            cout < < str < < endl;
   Exp:
      這個問題的考察點是sizeof的用法。那麼我們應該如何看待這個問題呢?
    1、這裡首先我們需要知道的是sizeof 是個運算子, 它具有運算的優先順序別, 那麼sizeof運算的優先順序在什麼地方呢?
       可以查看運算子優先順序的定義: sizeof 的優先順序和 *p(P為指標)、&p(變數,取地址)的優先順序一樣, 排在優先順序的第二位。
    2、其次要明白sizeof關鍵字的作用
          sizeof 關鍵字返回的是運算元在記憶體中佔用的位元組數。
       這裡要看sizeof操作符的操作對象:
       1) 類型關鍵字
           sizeof(int):  這個取決系統的定義, 當在32位機器上時; sizeof int == 4
                            而在16位機器上時, sizeof int == 2
       2) 變數
           int iTest;
           sizeof iTest;  這樣返回的是這種變數類型在記憶體中所佔用的空間。
           即:
                sizeof iTest == sizeof int;
       3) 字串字面值
           sizeof "abcd";
           那麼返回的是:字串在記憶體空進中佔用的位元組數。 這裡我們知道"abcd"在記憶體中佔用的是5個位元組,那麼很顯然有
           sizeof "abcd"==5;
       4) 數組
         這裡有點難度
         char chTest[5];
         sizeof(chTest)==5; //這裡可以知道chTest數組有5個元素,並且每個元素佔用一個位元組,因此sizeof(chTest)==5;

         那麼如果我們這樣定義呢?
         int iTest[5];
         sizeof(iTest)= ?  // 答案是10 , 因為有5個元素,每個元素佔兩個位元組,所以佔用10個位元組的空間。
     
         二維數組呢?
         char chTest[10][20];
         sizeof(chTest)= ?  //200
         既然sizeof(chTest)==200; 那麼sizeof(chTest[10])= ?  答案是 20 .
       
         又如:
         int iTest[10][20];
         sizeof(iTest)= ?  // 400
         同樣 sizeof(iTest[10])= ?  答案是 20

        通過這裡我們得出結論:
        對於sizeof運算元組的時候要分兩種情況:
        a、 一維數組
           sizeof(數組名) 返回的是 數組元素個數 * 每個元素佔用的位元組數
           sizeof(數組名[n]) 返回的是: 數群組類型定義的單個變數所佔用的位元組數
          即:
              int iTest[4];
          則
              sizeof(iTest)=8;
              sizeof[iTest[1]]=2;  //這裡假設 sizeof[int]=2
            
       b、 多維陣列
           sizeof(數組名)     返回的是:一維的長度*二維的長度*....* 每個元素佔用的位元組數
           sizeof(數組名[n])  返回的是:其後面各位長度的乘積* 每個元素佔用的位元組數,
                               這樣必須保證sizeof的運算元沒有取到最後一維。
           即: int iTest[2][3][4];
                sizeof(iTest[2][3])= 4*sizeof[int]=8;  //這裡假設用的是16位系統
       c) 多維陣列
          sizeof(陣列變數定義式);
          即:
          int iTest[2][3][4][5];
          sizeof(iTest[2][3][4][5])= ? 
          這裡返回的是 數組的維數 就是 4 。
       
       5、傳遞的是指標的時候
          如果操作的是指標那麼情形又如何呢?
          這裡也分兩種情形:
          1)當運算元是指標本身的時候
          Exp:
             int *iTest;
          那麼
             sizeof(iTest) = ? //這裡有一個規則,當sizeof操作變數的時候,返回的是變數本身的儲存長度, 因此
                                  //如果在16位的系統中, 這裡返回2; 而在32位系統中返回的是4;
                     
          2)當運算元有* 取值間接運算子號時
          Exp:
             int *iTest;
          那麼
             sizeof(*iTest) = ? // 這裡返回的是 2, 其實返回的是sizeof(int)的長度; 即返回的是其指向的
                                  //變數類型的 所佔用的空間
         可以用:
             float *fTest;
            sizeof(*fTest)= ?  // 這裡返回的值是 4
            sizeof(fTest)= ?     //  取決於系統  16位的系統返回 2, 32位系統返回 4, 64位系統返回8 即地址匯流排的寬度。

       現在回到我們的問題:
        void UpperCase( char str[] ) // 將 str 中的小寫字母轉換成大寫字母
           {   
                for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )      
                   if( 'a' <=str[i] && str[i] <='z' )           
                             str[i] -= ('a'-'A' );
             }
            char str[] = "aBcDe";
            cout < < "str字元長度為: " < < sizeof(str)/sizeof(str[0]) < < endl;
            UpperCase( str );
            cout < < str < < endl;  
      1、首先確定sizeof的文法問題:
            for( size_t i=0; i <sizeof(str)/sizeof(str[0]); ++i )    //文法沒有問題        
           
            sizeof(str)/sizeof(str[0])    //文法也沒有問題
      2、接著確定邏輯有沒有問題
            我們先看: sizeof(str[0])分析可知str[0]是個char的變數 , 因此佔用一個位元組;
            再看:
                 sizeof(str); 這裡str是一維數組同時是數組名, 因此返回的是數組的長度,
            貌似可以實現. 但是我們忽略了一個問題:
            數組當做實參傳遞的時候,最後一個 ‘\0’是不會傳遞的。
       3、 既然不能傳遞那麼我們啟動並執行時候是否可以得到正確結果呢

            答案是肯定的。

           這個可以在VC6.0中用下列代碼測試:
         Exp:
/*
 * test the sizeof key word
 *
 */

#include <stdio.h>
#include <conio.h>

 void UpperCase( char str[] ) 
{   int i;
    printf("%d,%d",sizeof(str),sizeof(str[0]));
    for(i=0; i< sizeof(str)/sizeof(str[0]) ;++i )
        if( 'a' <=str[i] && str[i] <='z' )
               str[i] -= ('a'-'A' );
}
int main(int argc,char *argv[])
{
    char  chTest[]="abcd";
    printf("%d\n",sizeof(chTest));
    UpperCase(chTest);

    puts(chTest); // 因為我們知道chTest[4]='\0'. 所以雖然沒有傳遞,但是還是可以實現轉換的功能
    getch();
}

   通過這個例子可以看出來, 有些時候確實不是我們想的那樣,

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.