C 指標與記憶體四區提高(1)

2021-07-05 18:37:23 字數 4593 閱讀 3904

一種例外情況是,將sizeof運算子用於陣列名時,將返回整個陣列的位元組長度。而sizeof乙個指標,只會返回乙個固定的值,一般為4個位元組。

實參arr和形參a的資料型別本質不一樣,所以sizeof的結果不一樣。

遍歷陣列需要將陣列位址連同陣列長度一起作為入參傳進去。

形參寫在函式上和寫在函式內作用是一樣的,只不過寫在函式上具有對外的屬性而已(也就是說可以通過實參傳給形參的方式來初始化它)。

結論:

arr代表陣列首元素的位址。

&arr代表整個陣列的位址。

arr+1 與 &arr+1 的結果不一樣,是因為arr與&arr所代表的資料型別不一樣,也可以說是指標的步長不一樣。arr是乙個int型別指標(* int)(是乙個4個位元組的記憶體位址),&arr是int陣列型別指標(int (*)[10])(是乙個40個位元組的記憶體位址)。

c/c++編譯器把陣列名(arr)處理為乙個常量指標,所以不能修改它,arr = arr+1會報錯,p = p+1則不會報錯。

經典總結:資料型別的本質就是固定大小記憶體塊的別名。

資料型別是c/c++編譯器為了方便的表達現實生活中的人事物而引入的乙個概念。

經典總結:變數的本質就是(一段連續)記憶體空間的別名(是一段記憶體空間的編號,類似於乙個門牌號)。

既然資料型別和變數都是記憶體塊的別名,這段記憶體塊就可以有多個別名,那麼如何增加新的別名呢?如下:

(1)、對資料型別取別名:

typedef

int integer

integer a = 10;

// int、integer都是int所代表的的資料型別的別名

typedef

struct teacher

teacher;

teacher t1;

(2)、對記憶體空間取別名:引用就是某一變數(目標)的記憶體空間的乙個別名,對引用的操作與對變數直接操作完全一樣。

引用的宣告方法:型別識別符號 &引用名=目標變數名;

int a; // 假如變數a指向的int型記憶體空間首位址為0x36345

int &ra=a; //定義引用ra,它是變數a的引用

以0x36345開始的4個位元組的這個記憶體位址,剛才他有個別名a,現在又有個別名ra了。

說明:(1)&在此不是求位址運算,而是起標識作用。

(2)型別識別符號是指目標變數的型別。

(3)宣告引用時,必須同時對其進行初始化。

(4)引用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,且不能再把該引用名作為其他變數名的別名。

ra=1; 等價於 a=1;

(5)宣告乙個引用,不是新定義了乙個變數,它只表示該引用名是目標變數名的乙個別名,它本身不是一種資料型別,因此引用本身不佔儲存單元,系統也不給引用分配儲存單元。故:對引用求位址,就是對目標變數求位址。&ra與&a相等。

(6)不能建立陣列的引用。因為陣列是乙個由若干個元素所組成的集合,所以無法建立乙個陣列的別名。

棧的屬性和buf位址增長方向是兩個不同的概念

一般情況下:棧的生長方向開口向下,堆的生長方向開口向上

void main()
不管棧開口向上還是向下,buf記憶體位址永遠向上的。

(1)、指標變數和它指向的記憶體塊是兩個不同的概念

int

*p = &a;

a、給p賦值p=0x12345; p = p+1; 只會改變指標變數的值,不會改變所指向的記憶體塊的值。

b、給*p賦值*p=1111; 不會改變指標變數的值,只會改變所指向的記憶體塊的值。

c、*p放在等號左邊——>給記憶體賦值 ——> 保證所指向的記憶體塊能修改

d、*p放在等號右邊——>從記憶體獲取值

(2)、指標也是一種資料型別,是指它指向的記憶體空間的資料型別

指標可以看做是一種復合資料型別,依附於它所指向的記憶體空間的資料型別的一種資料型別。

指標步長(p++),根據所指記憶體空間的資料型別來確定。

如:

intarr[4] = ;

arr++; // 指向陣列首元素的位址,該位址段代表的資料型別是int型別,所以步長是4

&arr++;// 指向整個陣列的位址,該位址段代表的資料型別是陣列型別,所以步長是4*4=16

經典總結:指標指向誰,就把誰的位址賦值給指標。指標的資料型別決定了指標的步長。(3)野指標產生的原因指標變數和它所指向的記憶體空間變數是兩個不同的概念。

釋放了指標所指的記憶體空間, 但是指標變數本身沒有重置為null,造成釋放的時候出現野指標。

char * p = null;

p = (char *)malloc(100);

if (p ==null)

if (p !=null)

if (p !=null)

避免方法:定義指標的時候,初始化為null,釋放指標所指的記憶體空間後,重置指標變數為null。

函式呼叫時,用實參取位址傳遞給形參,在被呼叫函式裡面用*p來改變實參,這樣就相當於把執行結果傳遞出來了。

通過把記憶體的首位址以形參的方式傳遞過去,實現不同的函式可以同時操作一塊記憶體空間。

間接賦值是指標做函式引數的精華,主函式和被調函式直接通過記憶體交換運算結果。

#define _crt_secure_no_warnings 

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

// 指標做函式引數,使用輸入輸出特性的

int getmem(char **param1/*out*/, int *length1/*out*/, char **param2/*out*/, int *length2/*out*/)

int main()

printf("p1=%s \n", p1);

printf("len1=%d \n", len1);

printf("p2=%s \n", p2);

printf("len2=%d \n", len2);

// 釋放堆記憶體

if (p1 != null)

if (p2 != null)

system("pause");

return

0;}

間接賦值推論在函式呼叫時:

用1級指標形參,去間接修改了0級指標(實參)的值。

用2級指標形參,去間接修改了1級指標(實參)的值。

用n級指標形參,去間接修改了n-1級指標(實參)的值。

(1) 主調函式可以把堆區、棧區、全域性資料區記憶體位址傳遞給被調函式。

(2)被調函式只能返回堆區、全域性區資料。

(3)指標做函式引數,是有輸入輸出特性的。

1 記憶體四區

資料型別的概念 型別 是對資料的抽象,型別相同的資料有相同的表現形式 儲存格式以及相關的操作。程式當中使用的所有資料都必定屬於某一種資料型別。資料型別的本質 資料型別可以理解為建立變數的模具,是固定記憶體大小的別名。資料型別為編譯器預算物件 變數 分配指定的記憶體空間大小。資料型別的別名 inclu...

C 記憶體四區

c語言中,記憶體分為四個區域,區,全域性區,棧區,堆區。我們寫的 會被編譯成機器語言存放在這個區域內。一般存放的是兩種型別的變數 全域性變數,靜態變數,常量。特點是由系統分配空間,直到程式結束才釋放。定義在函式體外面的變數是全域性變數 int func int a 0 這是乙個全域性變數 intma...

C 記憶體四區

c 程式在執行時,將記憶體大方向劃分為4個區域 1.區 存放函式體的二進位制 由作業系統進行管理 存放cpu執行的機器指令 區是共享的,共享的目的是對於頻繁被執行的程式,只需要在記憶體中有乙份即可。區是唯讀的,使其唯讀的原因是防止程式意外的修改了它的意義,2.全域性區 存放全域性變數,靜態變數和全域...