Understanding and using c pointers 第一章讀書筆記

 指針和內存
當C程序被編譯後,它與三種內存打交道
1.Static/Global
靜態變量以及全局變量被分配到該部分內存,他們在程序開始運行時被創建直到程序運行結束後纔回收生存期貫穿整個程序執行過程
2.Automatic(自動變量)
在函數中聲明的變量在函數運行時創建,其範圍僅限於函數內部,其生存期也僅限於函數執行時
3.Dynamic(動態內存分配)
內存從堆中分配並在必要時可以被釋放

如圖:

C語言參考中對語法和語意定義相當好,但是百密一疏,也有很多不確定的
1.Implementation-defined
2.Unspecified
 提供了一些實現但是沒有文檔描述。一個例子就是使用malloc()函數申請內存時參數傳0。
3.Undefined
 因爲沒有任何要求,所以可能發生任何結果

 

星號*有三種意思
1.乘法如:1 * 2;
2.聲明一個指針如:int* p;
3.求指針所指向的值如:*p = 3;

 

指針的實現其內部並沒有任何可以判定指針所指內容是否合法或其所指向的數據類型。

 

Null的概念
The NULL macro 0強轉爲void指針,許多庫中其定義爲:#define NULL ((void*)0),這是我們通常認爲的null指針,在很多頭文件 stddef.h, stdlib.h, and stdio.h等都有定義
The ASCII NUL 字符串終結符,但並沒有在任何標準頭文件中定義,數值上用一個全0的byte表示
A null string 空字符串,不包含任何字符(an empty string and does not contain any characters)

 

Pointer to void(void指針)
void指針在表示以及內存對齊方面與char指針相同(注意是char指針,不是char)
除非兩個void指針都被賦值爲NULL,否則void指針不與任何指針相等。

 

如果一個指針被聲明爲全局或者靜態變量,程序開始時他被初始化爲NULL

int *globalpi;

void foo()
{
	static int *staticpi;
	...
}

main()
{
	...
}

內存分配示意圖如下:

函數指針可能與數據指針的大小不同

 

Predefined Pointer-Related Types(與指針有關的預定義類型)
size_t,無符號數,malloc()參數就是它

#ifndef __SIZE_T
#define __SIZE_T
typedef unsigned int size_t;
#endif

ptrdiff_t 進行指針運算
intptr_t與uintptr_t
The types intptr_t and uintptr_t are used for storing pointer addresses. They provide a portable and safe way of declaring pointers, and will be the same size as the underlying pointer used on the system. They are useful for converting pointers to their integer representation.

 

儘量避免將指針轉換爲整形,在64位機器上如果整形只有4個字節則會出現信息丟失。

 

指針運算
1.指針與整數相加
2.指針與整數相減
3.兩個指針相減
4.指針比較

 

void指針與加法
作爲擴展,大多數編譯器允許void指針進行指針運算,但是很可能編譯器會報警告或者錯誤

int num = 5;
void* pv = #
printf("%p\n",pv);
pv = pv + 1;	/* 可能會有警告 */

兩個指針相減

int vector[] = {28,41,7};
int *p0 = vector;
int *p1 = vector + 1;
int *p2 = vector + 2;

printf("p2-p0: %d\n",p2-p0);	/* p2-p0: 2 */
printf("p2-p1: %d\n",p2-p1);	/* p2-p1: 1 */
printf("p0-p1: %d\n",p0-p1);	/* p0-p1: -1 */

指針比較(略去)

 

常量與指針(Constants and Points)

 

指向常數的指針(Pointers to a constant)

指針可以被定義爲指向常數。這意味着不能用指針修改其所指向的數據如:

int num = 5;
const int limit = 500;
int *pi;	//Pointer to an integer
const int *pci;		//Pointer to a constant integer
pi = #
pci = &limit;

指針本身可以被修改指向別的常整數(constant integer)或者簡單常數,如:pci = #是合法的,但是*pci = 200;就會報語法錯誤,因爲在用指針修改其所指向的內容。
下圖中,虛線表示指針可以指向對應數據類型,pci指向的灰色方塊表示不能用pci來修改。

將pci聲明爲指向常整數的指針意味着:

pci can be assigned to point to different constant integers
pci can be assigned to point to different nonconstant integers
pci can be dereferenced for reading purposes
pci cannot be dereferenced to change what it points to

The order of the type and the const keyword is not important. 下面兩句是等價的

const int *pci;
int const *pci;

 

常量指針指向非常數(Constant pointers to nonconstants)

聲明這種指針意味着指針本身不能改變,但是指針所指向的數據是可以改變的。例子如下:

int num;
int *const cpi = #

在這個聲明中:
cpi必須被初始化爲一個非常數的變量(cpi must be initialized to a nonconstant variable)
cpi不能被修改
cpi所指向的數據可被修改
如圖:

可以使用cpi修改所指向的數據,如:*cpi = 25; 但如果初始化時將其指向常量limit,就會出現編譯警告

const int limit = 200;
int *const cpi = &limit; /*warning: initialization discards qualifiers from pointer target type*/

一旦爲cpi賦於一個地址後我們不能像下面一樣在給其賦予別的值

int num;
int age;
int *const cpi = #
cpi = &age; /* 'cpi' : you cannot assign to a variable that is const */

 

指向常量的常量指針(Constant pointers to constants)
這種指針不常見,指針本身不能被修改,也不能通過指針修改其指向的數據,例子如下:
const int *const cpci = &limit;解釋如下圖:

這種指針聲明後必須初始化如:

int num;
const int * const cpci = #

不初始化的話會報錯,初始化以後再對指針賦值也會報錯如:

cpci = &limit;
*cpci = 200;
這樣也會報錯

 

指向 指向常量的常量指針 的指針 Pointer to (constant pointer to constant)
吐槽一下:這丫的真是複雜
這種指針有多級間接指引(indirection),聲明如下:

const int * const cpci = &limit;
const int * const * pcpci;	/* 聲明這種指針 */如下圖所示:



 

其使用如下:

printf("%d\n",*cpci);
pcpci = &cpci;
printf("%d\n",**pcpci);


常量與指針的對應關係如下圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章