C 可否對記憶體進行直接的操作

2022-03-19 17:22:44 字數 2528 閱讀 3329

c#可否對記憶體進行直接的操作 ?

可以使用指標

在這篇文章中將描述c#的乙個特性指標和所謂的不安全**。

非安全**

非安全**就是不在 clr 完全控制下執行的**,它有可能會導致一些問題,因此他們必須用 「unsafe」 進行表明:

unsafe

在其他一些地方也可以使用關鍵字 『unsafe』,例如我們可以將類或方法表明為非安全的:

unsafe class class1 {}

static unsafe void fastmove ( int* pi, int* pdi, int length)  

『unsafe』 關鍵字的必要性是它可以防止程式設計師的一些意外的用法。你可能會問既然是不安全的為什麼還有人要用它。答案就是有時候,在有些情況下,還需要用到指標。

指標指標是一種用來儲存其他變數位址的特殊的變數,如果你把第乙個變數的位址賦給第二個變數,你可以說第乙個變數是指向第二個,clr支援3種指標型別:受託管指標, 非託管指標和非託管函式指標。受託管指標儲存在堆上的託管塊的引用,乙個非託管指標是傳統的c++指標並且每次使用必須要放在unsafe**塊中,乙個非託管函式指標也是指向函式位址的傳統的c++指標(delegates 可以被看做是非託管函式指標).

你可以像下面這樣的宣告來建立指標:型別* 變數_名稱; 

既然型別可以是任意乙個非引用型別並且不包含引用型別字段,它只能是:sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool 和列舉型別以及其他指標型別,也可以是任何使用者自定義的包括非託管型別欄位的結構體.

下面是不同型別指標宣告的示例:

int* pi //declaration a pointer to integer variable

float* pf, pq // two pointers to float variables. not *pf, *pq 

char* pz // pointer to char

就像前面說的非託管**clr是不能驗證的,為了編譯你需要指定 /unsafe 編譯選項,如果你是使用的是microsoft visual studio你需要在專案選項中把 'allow unsafe code block'設定成 true。

指標的基本用法

還有一些與指標緊密聯絡的操作符,那就是 & 操作符,& 返回它所操作物件的位址。

例如:unsafe 

在這個例子中我們建立了2個變數,』pi』是指向int的指標,』x』是int,然後我們將』x』在記憶體中的位址賦予』pi』,理解我們放在 』pi』 變數中的是 』x』的位址而不是』x』的值非常重要 (使用: pi = x 將返回錯誤 "cannot implicitly convert type 'int' to 'int*'")

編譯後執行將會輸出:

value of x is: 1 

指標可以接受 null 值,也可能使用 void 指標型別,下面的**可以正常編譯:

unsafe 

fixed 關鍵字和垃圾**

在 c# 中使用指標需要比在 c++種更加注意。這是因為垃圾**器(g.c.)會執行記憶體清理,在清理的過程中,g.c.會改變物件的物理記憶體位置,如果 g.c.改變了物件的位置指標將指向錯誤的記憶體位置。為了避免這樣的問題(已經與垃圾**器連線),c# 包含 'fixed' 關鍵字. 它通知系統不要讓垃圾**器重新部署物件。

如果我們忘了 』fixed』 關鍵字編譯器會給我們相應的警告,但它沒有智慧型到在下面的情況中也會警告我們。下面的**有乙個嚴重的bug儘管編譯很正常。

c# 指標和 winapi

使用指標最重要的好處就是可以與其他二進位制**進行互動。許多 winapi 函式都使用指標,例如getcomputername (kernel32.lib.)可以提供我們的計算機的名稱。

bool getcomputername(lptstr lpbuffer, // computer name

lpdword lpnsize // size of name buffer);

下面的程式演示如何使用getcomputername:

[system.runtime.interopservices.dllimport("kernel32")]

static extern unsafe bool getcomputername(byte* lpbuffer,long* nsize);

static void main()

}system.text.encoding textenc = new system.text.asciiencoding();

system.console.writeline("computer name: ",textenc.getstring(buffor)); }結論

我們已經看到指標是c#語言中非常有用的部分,使用指標並不難但是要非常小心,因為有可能會導致難以診斷的問題,使用指標會擾亂垃圾**器的功能,特別當我們在程式中大量使用指標。因此在之用指標之前我們應該多考慮,或者嘗試其他的解決辦法。

C 可否對記憶體進行直接的操作

可以使用指標 在這篇文章中將描述c 的乙個特性指標和所謂的不安全 非安全 非安全 就是不在 clr 完全控制下執行的 它有可能會導致一些問題,因此他們必須用 unsafe 進行表明 unsafe 在其他一些地方也可以使用關鍵字 unsafe 例如我們可以將類或方法表明為非安全的 unsafe cla...

c語言對記憶體位址的直接操作(讀ARM有感)

在arm中看到了 define rwtcon volatile unsigned 0x03000000 然後在函式呼叫中對這位址直接賦值,rwtcon pclk 100000 1 8 3 3 剛看到這嚇我一跳,以前只聽說過沒有看過,這裡還真這樣幹了,這就是c語言中的直接對記憶體賦值,以上的語句還真有...

注意!C 值傳遞對記憶體進行全拷貝!

很多剛學c 的程式設計師寫 時,不會特別注意函式引數的傳遞方式,對cstring等型別引數會直接使用值傳遞的方式,下面我們通過一段 驗證下值傳遞對程式記憶體及效能的影響。為了能直觀的看到對比結果,我們分別以std list和c array舉例,源 及記憶體情況如下 通過對比圖可以看到,std lis...