Expert C Programming (Page 19)衍生出的思考總結

來源:互聯網
上載者:User
文章目錄
  • 一、賦值時帶限定符問題(qualifier)
  • 二、賦值時符號與無符號類型問題
  • 三、文字量、變數取地址的類型問題
一、賦值時帶限定符問題(qualifier)

修飾符包括 const, static, ...

挑戰你的極限,你看看哪些賦值編譯器會報錯/警告?

 

左實值型別 右實值型別 可否賦值 解釋
       
普通類型之間賦值      
char const char  
const char 任何異己char  
       
指標類型之間賦值      
char * const char *  
char * char * const  
char * const char * const  
const char * char *  
const char * char * const  
const char * const char * const  
char ** char * const *  
char ** char * const * const  
char ** const char **  
char ** const char * const *  
char ** const char * const * const  
char ** char ** const  
const char ** char **  
const char ** char * const *  
const char ** char * const * const  
const char ** const char * const *  
const char ** const char * const * const  
const char ** char ** const  
const char ** const char ** const  
char * const * char **  
char * const * const char **  
char * const * char * const * const  
char * const * const char * const *  
char * const * const char * const * const  
char * const * const char ** const  
char * const * char ** const  
(const) char * (const) * const 任何異己指標  

 

如果沒有清楚,請查詢ISO C具體章節,仔細體味。

char * const * char **

1. 對於普通類型賦值: 規則很簡單

2. 對於指標類型賦值:

補充:如果右邊指標指向的類型不帶限定符,左邊指標指向的類型可以多加修飾符,如:

const char * char *
char * const * char **
const char * const * const char **

 

二、賦值時符號與無符號類型問題

 

三、文字量、變數取地址的類型問題

變數/常量取地址:

是一個const指標類型,此指標不允許再指向其他地址。

注意:變數和常量都是需要分配儲存空間的,只是其值是否唯讀這種限定的區別而已。

很簡單的測試:

#include <stdio.h>
 
int main()
{
    int i=0;
    int j=1;
    &i=&j;
 
    return 0;
}

編譯錯誤: 無效的左值

&i的類型應該為int * const
#include <stdio.h>
 
int main()
{
    const int i=0;
    ++*(&i);
 
    return 0;
}

編譯錯誤。

&i的類型應該是const int * const

 

文字量取地址:

一般來說,內建類型的文字量都是編譯時間直接計算出來,表現在彙編層級就是"立即數"(immi )。於是它們不存在地址的問題。這些文字量包括比如1, 1.23以及宏展開,它們是不佔用儲存空間。

於是,對上述文字量取地址是非法的. 即&操作符不允許應用到上述的文字量。你試試:

#include <stdio.h>
 
int main()
{
    int * ptr = &0;
 
    return 0;
}

編譯通不過:invalid lvalue in unary `&'  

 

但是唯一可以取地址操作的文字量是:字串!

#include <stdio.h>
 
int main()
{
    char * ptr = (char *)&("this is a string");
 
    return 0;
}

OK, 編譯沒問題!

其中,

char * ptr = &("this is a string");
等價於
char * ptr = "this is a string";
C語言在語言層面在做了上述簡化的等價保證

字串文字量是占儲存空間的,它們一般分配到唯讀區,因此對它們取地址的類型應該是const char * const. 依照第一部分的總結,此地址可以賦給char *或者const  char *

測試:

#include <stdio.h>
 
int main()
{
    char * ptr = (char *)&("this is a string");
 
    *ptr = 'r';
 
    printf("%c", *ptr);
 
    return 0;
}

編譯可以通過?!

沒什麼好奇怪的!因為編譯期是靜態類型檢查,ptr的靜態類型是char *,但是實際上它指向的是const char, 所以它騙過了編譯器。編譯器可夠愚蠢了:)

但是,罪犯會逍遙於法外嗎?不會

果不其然,運行時事發東窗了,運行時異常出錯!

像上面的錯誤,如果剛開始就寫成

const char * ptr = (char *)&("this is a string");

那麼,在編譯期就可以報錯!

同樣結果也出現在:

#include <stdio.h>
 
int main()
{
    char * ptr = "this is a string";
 
    *ptr = 'r';
 
    printf("%c", *ptr);
 
    return 0;
}

總結:

1. 明確搞清楚取地址後的文字量、常量、變數的類型,當將它們賦給其他指標時,此指標類型最好寫明確,以避免出現編譯器正確,運行時卻報錯的問題

2

 

本文中總結賦值時一些類型的問題,在函數參數傳遞中用到這些規則。請見http://www.cnblogs.com/chio/archive/2008/09/21/1295082.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.