標籤:

關於typedef的疑問?

首先看代碼:

typedef char* pchar;

const pchar cstr = "aaaa";

cstr = "bbbb";//這一行編譯報錯,錯誤代碼C3892,說是表達式必須是可修改的左值

問題是,難道pchar不應該被當成【char*】的文本替換嗎,如果是這樣的話,上面那兩行代碼就被編譯器改成:

const char* cstr = "aaaa";

cstr = "bbbb";

這種形式,而這種形式不應該報錯啊?


你的理解有誤,這裡不會被替換為

const char* cstr = "aaaa"

而是

char* const cstr = "aaaa"

typedef不是文本替換,他是引入了一個新的類型, 如這裡的pchar 即 char* ,而const qualifier 則用在 object 本身,而非其他類型,這被稱為 top-level const.

以這裡的例子來闡述,這裡你可以理解為如下:

const pchar cstr = "aaa";
====&>
const (char*) cstr = "aaa";
====&>
(char*) const cstr = "aaa";
====&>
char* const cstr = "aaa";

所以 cstr 被 const 修飾而不能被修改。若你使用clang,可以通過ast-dump查看到更多信息,如:

Note: 其中-Xclang 用於進入 Clang 編譯器前端 Driver, -ast-dump 是Clang編譯器前端選項,而非用於接收普通編譯選項,如-c -o -fopenmp等。


不是文本替換,關於const一個簡單的判定方式:把定義中類型都去掉,看修飾什麼

const pchar str

如果是#define pchar char *,那麼先文本替換為

const char *str

然後去掉類型char,則const修飾的*str,即str指向內容不能改,但str本身不是const

但如果是typedef char *pchar,則pchar是一個和char *等同的獨立的類型,判定時候作為一個類型去掉,則剩下就是const str,即str本身不可變


const pchar cstr;

等價於

char* const cstr;

而不是

const char* cstr;

typedef 不是文本替換。


typedef 不是文本替換,而是給一種數據類型自定義一個別名。


typedef char* pchar;
const pchar // 可看成 (const (char*))
#define pchar char*
const pchar // 可看成 ((const char)*)

第一個 const 波及的是 char*

第二個 const 波及的是 char

C++ Primer 對此的解釋是反直覺的

在我看來, 把類型當作運算就好了

int* 就是一個指針類型

const int 也是一個類型

const int* 含義是 const int 的指針類型

int* const var 這時候 const 才算是 modifiler

然後, 請將所有代碼按如下風格寫

#define adrOf(val) (val)
#define valIn(adr) *(adr)
int number = 1;
int* number_ptr = adrOf(number);
int number_ref = number; // 應該被完全當作修飾符
int number_2 = ValIn(number_ptr);


typedef與#define還是有區別的!

特別是涉及指針與const搭配時!

#define是簡單的宏替換!

typedef卻是定義了一種類型的新的別名,與宏有別!

此處:

typedef char* pchar;

const pchar cstr = "aaaa";

你可以這樣去理解:

這裡的

const pchar cstr 和

const int i

沒什麼本質上的區別,都是對變數進行只讀限制,不過你這裡的變數cstr是你自己定義的新的類型的變數而不是編程語言自有的基本類型的變數而已!

所以,你這裡並不是簡單的替換成了const char*!

而是char*const

如果你想定義const char*類型,可以這樣:typedef const char* pchar


這個在C++primer 第五版 61頁上有特別提到過。

typedef char* pchar;

//pchar本質的類型為指針

const pchar cstr = "aaaa";

//cstr為常量指針(const pointer),指針指向的地址不能改變

cstr = "bbbb";

//cstr又指向了另外一個地址,這當然是錯的啦

//cstr為常量指針,不能當左值使用了

此外

const char *p = "hello word";

//這個呢 const char是基本類型,意思是p是一個指向 const char 類型的指針,p還可指向其他的const char變數

手機碼字各種不方便(,,?ω?,,)


c++ primer 英文版第五版 p68


typedef不是直接文本替換,而是類型別名。可以拿c++中STL旁徵博引一次。假設一個容器定義如下:

vector& iv;

基礎知識:容器中的迭代器其實就是一個范化指針。那麼我們可以取上面容器的一個迭代器,如下:

vector&::iterator iter;

上面的迭代器就是很一般的迭代器,類似於一般的指針,不加const.記住iter是一個迭代器哦。那我們現在要取一個常量迭代器,即此迭代器只能終生指向一個內存地址,並且在定義的時候就初始化。那怎麼寫呢?c++的寫法如下:

const vector&::iterator iter;

而它的對立面卻是vector &::const_iterator iter;

話說這麼多,一個目的,拓展一下,是說給明白人看的。


這個在C語言495問題里好像有,這裡cstr是const 指針內容(地址)不能被修改


補充一下。感覺可以從c語言語法的角度來理解為什麼const pchar和const char *不同。首先typedef定義使得char *成為一個獨立的不可分割的類型。const是一個type qualifier,用來修飾一個類型的,所以可以讀成cstr是只讀pchar類型,展開就是cstr是只讀的指向char的指針。而const int *的話,其實pointer(*)從語法角度看,它屬於declarator的組成部分,而不是類型的一部分,比如 some_type *p表示指向類型some_type的指針。 所以const int *讀成指向const int的指針。


typedef是定義一種新的數據類型,而const是修飾數據類型的


推薦閱讀:

如何評價只有 LLVM 10% 代碼的 QBE?
如何學習JIT,能提供一些系統全面的路線和材料嗎?
想編寫一個虎書中的編譯器,該如何上手?

TAG:CC | 編譯器 |