C 查缺補漏之陣列與指標

2021-06-29 03:08:48 字數 3797 閱讀 4227

陣列的維數必須使用大於等於一的常量表示式來定義,此常量表示式只能包含整型字面值常量,列舉型別,或者用常量表示式初始化的整型,非const變數和到執行階段才知道其值的const變數都不能用來定義陣列的維數

/** ok 字面值常量 */

int array[10];

/** ok 列舉型別*/

enum arraysize;

int array2[size1];

/** ok 字面值常量初始化的const整型*/

const unsigned int arraysize =10;

int array3[arraysize];

/** error 非const整型 */

int arraysize = 10;

int array[arraysize];//error: array bound is not an integer constant before ']' token int array[arraysize];

/** error 在執行時才知道陣列的大小 */

const int arraysize = getsize();

int array[arraysize];

注:這樣在執行時才知道維數的寫法在g++上面編譯沒問題,但是在vc6上面編譯不通過,所以還是建議不要這樣寫(可能是g++版本比vc6高出好多)

注意:陣列的大小一旦確定就不能再更改,如果需要再想向輸入裡面插入元素,建議使用vector,或者操作記憶體,分配一塊更大的記憶體(realloc)

陣列的下標一般來說是size_t型別的,在我們程式設計過程中如果忘記檢查陣列的下標是否越界時,可能會造成「緩衝區溢位」

什麼是指標?指標用於指向物件!

對於指標的初始化可以使用下面四中型別的值:

把int型別的值賦值給指標是非法的,但是把字面常量值0或者是初始化為0(除0以外的都不行)的const整型賦值給指標就行!

/** ok */

const int mynull = 0;

int * ptr = mynull;

/** error 只可以為0*/

const int mynull = 1;

int * ptr = mynull;

/** error 型別不匹配 */

double dnumber;

int * ptr = &dnumber;

/** ok 強制的型別轉換為相同型別的指標 */

double dnumber = 10.0;

//這裡會記憶體截斷(8位元組->4位元組),根據大端小端來指向dnumber在記憶體裡面的高四位元組或者低四位元組,一旦對ptr解引用,得到的資料是不可預知的!

int * ptr = (int *)(&dnumber);

printf("%d\n",*ptr);

c++提供了一種特殊的指標,他可以儲存任何型別的指標

/** ok */

int number = 10;

double dnumber = 10.0;

void * ptr = &number;

ptr = &dnumber;

注意:void * 指標表明他與一記憶體位址相關,但是不知道這塊記憶體的型別,所以我們不能對void *指標進行解引用操作,在解引用之前需要進行型別轉換!

void * 指標只只支援下面幾個有限的指標操作:

雖然指標和引用都可以間接訪問乙個值,但是他們之間還是有一些區別的:

引用總是指向某個物件的(一旦初始化,就永遠繫結同乙個特定物件),在定義引用時沒有初始化是錯誤的,而指標可以不指向任何物件(賦值為null)

在給引用賦值的時候,修改的是引用所繫結的物件,而給指標賦值時,修改的是指標本身的值,指標指向的物件沒有發生改變

c++裡面,指標和陣列密切相關,特別是在表示式中使用陣列名時,陣列名會自動轉化成為指向陣列第乙個元素的指標

指標和陣列的下標操作:

我們知道陣列的下標是size_t型別的,也就是unsigned型別的,但是對於指標來說也一定是這樣的嗎?下面我們來看乙個例子:

int intarray=;

int * ptr = &intarray[2];

for (int i = -2; i < 3; ++i)

這裡的ptr下標為-1 -2 都正常使用,這裡陣列的使用採用一種相對定址的方法,ptr位址+i的偏移,所以這裡可以採用相對定址

指向const指標定義如下:

const int * ptr ;

表明ptr指向的物件的值不能修改

const物件一定要用指向const物件的指標來指向,而非const物件既可以用一般指標來指向也可以使用指向const物件的指標來指向,說的有點拗口,下面我們來看一些例子:

/** ok */

const int number = 10;

const int * ptr = &number;

/** error number為const物件,需要用const指標來指向 */

const int number = 10;

int * ptr = &number;//如果這裡可以的話,那麼就可以通過ptr來為const物件賦值,這是極其危險的!

/** ok */

int number = 10;

const int * ptr = &number;

int * ptr = &number;

下面注意一點:如果是void 型別的指標,那麼不能用void *指向const物件,必須要使用const void * 才可以!

const指標定義如下:

int * const ptr;

表明ptr本身的值不能修改

/** error ptr的值不能修改 */

int number = 0;

int * const ptr = &number; 

ptr++;

/** ok 可以修改指向的物件的值*/

int number = 0;

int * const ptr = &number;

*ptr = 10;// number = 10;

顧名思義,就是指向乙個const的指標,指標自身的特性也是const型別的,指標指向的物件值不能改變,自身的指標值也不能改變

int * ptr = new int[-1];

int * ptr = new int [0];

要是申請的陣列的大小小於等於0會發生什麼?

int * ptr=null;

trycatch(std::bad_alloc e)

printf("%p\n" , ptr);

執行結果為

bad alloc

00000000

丟擲了bad_alloc 異常

那要是0呢?

int * ptr=null;

trycatch(std::bad_alloc e)

printf("%p\n" , ptr);

執行結果為

00481818

表明在0的時候分配陣列成功!那我們來對這個分配好的內粗操作

*ptr = 10;

printf("%d\n",*ptr );

輸出10

操作正常!!!在《c++ primer》上面寫的是不能進行解引用操作!求解釋???

在《c陷阱與缺陷》裡面提到過,c語言中沒有所謂的多維陣列,只不過是陣列的型別是陣列而已也就是說多維陣列起始就是這樣定義的:

typedef int array_t[3];

array_t array[2];

array就和定義為 array[2][3]一樣的;

c 查缺補漏

c 基本語法 c 初始化引數列表 c 預設建構函式 c 複製建構函式 三 複製控制 1 複製建構函式 1.1 幾個要點 1 複製建構函式 複製建構函式是一種特殊建構函式,只有1個形參,該形參 常用 const 修飾 是對該類型別的引用。class peopel 當定義乙個新物件並用乙個同型別的物件對...

C 查缺補漏之變數

我們在日常程式設計中經常會有int a 10 那麼 這個a就是變數。變數提供了程式可以操作的有名字的儲存區,要是在彙編時代,我們是直接操作暫存器和記憶體位址的,那麼現在就把底層的暫存器和記憶體位址抽象出來,取了乙個別名,通過這個別名也可以操作這塊記憶體。c 中每乙個兩邊都要有乙個特定的型別,該型別決...

C 查缺補漏之const限定符及引用

首先我們我們先來看乙個例子 for int i 0 i 10 i 上面的這個10在這裡迴圈裡面代表的是什麼意思呢?這個迴圈在做什麼事情呢?也就是說10這個數字的作用何在?在這裡,我們將這種不能表示任何意義的數字 比如這裡的10 稱之為魔數 magic number magic number在程式維護...