前言
閱讀《你必須知道的495個C語言問題》一書的過程中,提取自己在認知上有誤的地方,以及個人要點等相關知識點,便於加深記憶與日後查閱。
1.24 一個文件中定義一個extern數組,然後在另外一個文件中使用:
file1.c :
int array[] = {1,2,3};
file2.c :
extern int array[];
爲什麼在file2.c中,sizeof取不到array的大小?
答:未指定大小的extern數組是不完全類型。不能對它使用sizeof,因爲sizeof在編譯時發生作用,它不能獲得定義在另一個文件中的數組的大小。
你有三種選擇。
(1)在定義數組的文件中聲明、定義並初始化一個變量,用來保存數組的大小:
file1.c :
int array[] = {1,2,3};
int arraysz = sizeof(array);
file2.c:
extern int array[];
extern int arraysz;
(2)爲數組大小定義一個明白無誤的常量,以便在定義和extern聲明中都可以一致地使用:
file.h
#define ARRAY_SIZE 3
file1.c :
#include "file1.h"
int array[] = {1,2,3};
file2.c:
#include "file1.h"
extern int array[ARRAY_SIZE];
(3) 在數組的最後一個元素放入“哨兵”值(通常是0、-1、NULL),這樣代碼不需要數組大小也可以確定數組的長度:
file1.c :
int array[] = {1,2,3,-1};
file2.c:
extern int array[];
擴展說明:來源於《C語言深度剖析》一書,抱歉,字太多,只好截圖。
11.11 爲什麼不能向接受const char * * 的函數傳入char * * ?
答:可以向接受const T的指針的地方傳入T型的指針(任何類型都適用)。但是,這種允許在被限定的指針類型上輕微不匹配的規則(明顯的例外)卻不能遞歸調用,只能用於最上層。(因爲const char ** 是const char的指針的指針,所以這個例外規則並不適用。)
不能向const char * * 指針賦char * 值的原因有些晦澀。const限定詞既然存在,就是爲了讓編譯器幫助你保證不修改const值。這就是爲什麼可以將char 賦向const char *,但反過來卻不行。顯然,使普通指針“常數化”是安全的,但反之就危險了。
若還是一頭霧水,
請查看該參考博文:http://blog.chinaunix.net/uid-23629988-id-3064438.html
擴展思考:
1. const char *p; 或者char cosnt *p; // *p 不能修改
char *const p; // p 不能被修改
cosnt char *const p; // p 和 *p 不能被修改
2. cosnt char **p; 或者char const **p;
const char **const p;
cosnt char *const*const p;
const char *const*const*const p;
11.12 我這樣聲明:
typedef char *charp;
const charp p;
爲什麼是p而不是它所指向的字符爲const ?
**答:**typedef的替換並不完全是基於文本的。在聲明 const charp p;中,p被聲明爲const的原因跟const int i 將 i 聲明爲const的原因一樣。p的聲明不會“深入”typedef的內容來發現涉及了指針。
11.26 爲什麼我不能對void *指針進行算術運算
答:編譯器不知道所指對象的大小。(請記住,指針的算術運算總是基於所指對象的大小的。)因此不允許對void 指針進行算術運算(儘管有些編譯器作爲擴展允許這種運算)。在做運算之前,可以把指針轉化爲char 型或你準備操作的其他指針類型。