c语言中指针往内存写值,C语言编程常见问题解答之指针和内存分配
指針為C語言編程提供了強大的支持——如果你能正確而靈活地利用指針,你就可以直接切入問題的核心,或者將程序分割成一個個片斷。一個很好地利用了指針的程序會非常高效、簡潔和精致。
利用指針你可以將數據寫入內存中的任意位置,但是,一旦你的程序中有一個野指針("wild”pointer),即指向一個錯誤位置的指針,你的數據就危險了——存放在堆中的數據可能會被破壞,用來管理堆的數據結構也可能會被破壞,甚至操作系統的數據也可能會被修改,有時,上述三種破壞情況會同時發生。
此后可能發生的事情取決于這樣兩點:第一,內存中的數據被破壞的程度有多大;第二,內存中的被破壞的部分還要被使用多少次。在有些情況下,一些函數(可能是內存分配函數、自定義函數或標準庫函數)將立即(也可能稍晚一點)無法正常工作。在另外一些情況下,程序可能會終止運行并報告一條出錯消息;或者程序可能會掛起;或者程序可能會陷入死循環;或者程序可能會產生錯誤的結果;或者程序看上去仍在正常運行,因為程序沒有遭到本質的破壞。
值得注意的是,即使程序中已經發生了根本性的錯誤,程序有可能還會運行很長一段時間,然后才有明顯的失常表現;或者,在調試時,程序的運行完全正常,只有在用戶使用時,它才會失常。
在C語言程序中,任何野指針或越界的數組下標(out-of-bounds array subscript)都可能使系統崩潰。兩次釋放內存的操作也會導致這種結果。你可能見過一些C程序員編寫的程序中有嚴重的錯誤,現在你能知道其中的部分原因了。
有些內存分配工具能幫助你發現內存分配中存在的問題,例如漏洞(leak,見7.21),兩次釋放一個指針,野指針,越界下標,等等。但這些工具都是不通用的,它們只能在特定的操作系統中使用,甚至只能在特定版本的編譯程序中使用。如果你找到了這樣一種工具,試試看能不能用,因為它能為你節省許多時間,并能提高你的軟件的質量。
指針的算術運算是C語言(以及它的衍生體,例如C++)獨有的功能。匯編語言允許你對地址進行運算,但這種運算不涉及數據類型。大多數高級語言根本就不允許你對指針進行任何操作,你只能看一看指針指向哪里。
C指針的算術運算類似于街道地址的運算。假設你生活在一個城市中,那里的每一個街區的所有街道都有地址。街道的一側用連續的偶數作為地址,另一側用連續的奇數作為地址。如果你想知道River Rd.街道158號北邊第5家的地址,你不會把158和5相加,去找163號;你會先將5(你要往前數5家)乘以2(每家之間的地址間距),再和158相加,去找River Rd.街道的168號。同樣,如果一個指針指向地址158(十進制數)中的一個兩字節短整型值,將該指針加3=5,結 果將是一個指向地址168(十進制數)中的短整型值的指針(見7.7和7.8中對指針加減運算的詳細描述)。
街道地址的運算只能在一個特定的街區中進行,同樣,指針的算術運算也只能在一個特定的數組中進行。實際上,這并不是一種限制,因為指針的算術運算只有在一個特定的數組中進行才有意義。對指針的算術運算來說,一個數組并不必須是一個數組變量,例如函數malloc()或calloc()的返回值是一個指針,它指向一個在堆中申請到的數組。
指針的說明看起來有些使人感到費解,請看下例:
char *p;
上例中的說明表示,p是一個字符。符號“*”是指針運算符,也稱間接引用運算符。當程序間接引用一個指針時,實際上是引用指針所指向的數據。
在大多數計算機中,指針只有一種,但在有些計算機中,指向數據和指向函數的指針可以是不同的,或者指向字節(如char。指針和void *指針)和指向字的指針可以是不同的。這一點對sizeof運算符沒有什么影響。但是,有些C程序或程序員認為任何指針都會被存為一個int型的值,或者至少會被存為一個long型的值,這就無法保證了,尤其是在IBM PC兼容機上。
注意:以下討論與Macintosh或UNIX程序員無關;
最初的IBM PC兼容機使用的處理器無法有效地處理超過16位的指針(人們對這種結論仍有爭議。16位指針是偏移量,見9.3中對基地址和偏移量的討論)。盡管最初的IBM PC機最終也能使用20位指針,但頗費周折。因此,從一開始,基于IBM兼容機的各種各樣的軟件就試圖沖破這種限制。
為了使20位指針能指向數據,你需要指示編譯程序使用正確的存儲模式,例如緊縮存儲模式。在中存儲模式下,你可以用20位指針指向函數。在大和巨存儲模式下,用20位指針既可以指向數據,也可以指向函數。在任何一種存儲模式下,你都可能需要用到far指針(見7.18和7.19)。
基于286的系統可以沖破20位指針的限制,但實現起來有些困難。從386開始,IBM兼容機就可以使用真正的32位地址了,例如象MS-Windows和OS/2這樣一些操作系統就實現了這一點,但MS—DOS仍未實現。
如果你的MS—DOS程序用完了基本內存,你可能需要從擴充內存或擴展內存中分配更多的內存。許多版本的編譯程序和函數庫都提供了這種技術,但彼此之間有所差別。這些技術基本上是不通用的,有些能在絕大多數MS-DOS和MS-WindowsC編譯程序中使用,有些只能在少數特定的編譯程序中使用,還有一些只能在特定的附加函數庫的支持下使用。如果你手頭有能提供這種技術的軟件,你看一下它的文檔,以了解更詳細的信息。
7.1 什么是間接引用(indirection)?
對已說明的變量來說,變量名就是對變量值的直接引用。對指向變量或內存中的任何對象的指針來說,指針就是對對象值的間接引用。如果p是一個指針,p的值就是其對象的地址;*p表示“使間接引用運算符作用于p”,*p的值就是p所指向的對象的值。
*p是一個左值,和變量一樣,只要在*p的右邊加上賦值運算符,就可改變*p的值。如果p是一個指向常量的指針,*p就是一個不能修改的左值,即它不能被放到賦值運算符的左邊,請看下例:
例 7.1 一個間接引用的例子
#include int
main()
{
int i;
int * p ;
i = 5;
p = & i; / * now * p = = i * /
/ * %Pis described in FAQ VII. 28 * /
printf("i=%d, p=%P, * p= %d\n" , i, P, *p);
* p = 6; / * same as i = 6 * /
printf("i=%d, p=%P, * p= %d\n" , i, P, *P);
return 0; / * see FAQ XVI. 4 * / }
}
上例說明,如果p是一個指向變量i的指針,那么在i能出現的任何一個地方,你都可以用*p代替i。在上例中,使p指向i(p=&i)后,打印i或*p的結果是相同的;你甚至可以給*p賦值,其結果就象你給i賦值一樣。
C語言編程常見問題解答之指針和內存分配.doc
下載Word文檔到電腦,方便收藏和打印[全文共2694字]
編輯推薦:
下載Word文檔
總結
以上是生活随笔為你收集整理的c语言中指针往内存写值,C语言编程常见问题解答之指针和内存分配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 简单算法的举例c语言,计算机科学与技术系
- 下一篇: android jar 无法访问r文件,