C語言中的指針為什麼要區別出指向不同數據類型的指針?

比如 char *p = "hello,world";

p是指向字元的指針. 但是指針是一個存放內存地址的變數, 在內存編址中地址都是整數, 都是整數那聲明的時候為什麼不可以直接 *p = "hello", *p = 1234; 呢?


那就不是C而是彙編了。


指針如果沒有類型,那麼指針的「++」、或者「p=p+2」這樣的操作,既不知道要偏移多少了。

以p=p+2為例,編譯器會根據p的類型將這個語句翻譯成 p = p + 2 * (指針類型佔用的內存大小),如果沒有類型,這個語句就沒有辦法實現。但是到運行期,這個東西就看不見了。


好吧,如題主所說,char *p = "hello,world"; 指針不要類型,就寫成*p = "hello,world";假設編譯器允許這麼做的話,那麼編譯肯定能通過的。

在運行時,假設指針p的值是0x123,當p = p + 1的話,此時你說p應該怎麼加這個1呢?是加1個int佔用的位元組大小,還是加1個long佔用的位元組大小,還是加1個char佔用的位元組大小?

所以這就是在定義指針p時一定要聲明類型的原因。


為了讓編譯器知道指針++的時候需要移動多大的內存偏移


類型安全檢查是編譯器提供的重要功能,它可以讓你不用操心很多麻煩事。對於C語言,由於其類型系統過於羸弱,你可以用void型通用指針來繞開編譯器提供的類型檢查而自己寫一套類型系統,可參考《object oriented programming in ANSI C》


樓上的也都說了:

1. 數據類型佔用位元組不同

2. 便於你+1操作

那位元組數跟+1有個毛關係?當然有。

比如:

1. char 為 1個位元組(C中)

2. int 為 2個位元組

那麼:

定義char數組:char a[10],每次a++時都移動1個位元組。

定義int數組:int b[10],每次b++都移動2個位元組。

當然也不僅僅是移動,包括讀取(告訴機器連續讀幾個位元組)、賦值(新值從指針地址開始覆蓋幾個位元組)、刪除、修改等等都一樣。

其實不僅僅是指針,當你用int、double、char等定義變數時,也就是告訴底層該怎麼對這些變數進行操作


這其實是一個語言語法糖啊,有類型也就定義的時候多敲幾個字,後續使用加加減減就不用你管類型長度了。

沒有這個,你就得像彙編一樣精確計算並手寫不同類型的移動步長,萬一跨平台類型大小不同那就更糟了。


「地址是整數」這個說法,不對!你只能說「地址可以人為地用整數表示」。這涉及到計算機原理,希望你補補這方面知識。

而且即使我們可以把地址看作整數,也不能把指針都設置成同一個類型*,因為指針聲明的重點不是地址本身,而是這個地址連結著某個類型的數據(所謂類型,就是對01碼的編碼方式)。

問題補充里,char *p的意思是「生成一個p,讓它指向一小塊兒內存空間,這個空間里存字元串」。如果只有*,那麼計算機就不知道該用什麼編碼方式設置那個空間(char?int?long?還是float?),這就是C語言接近機器的地方,不像更高級的語言那樣,在編寫時不用顧忌類型,交給編譯器去編譯。

注意!——char *,是個數據類型,不能拆開看成char和*。它的意思是:有個char *型的數據,它是個地址,指向一個數據,並且這個數據是以char編碼方式編碼的。

另:C語言里,p具體是哪個地址,是我計算機的事,人類你不用管,要使用這個地址時敲p就可以了。

另另:在現有的C語言語法里, *p的*是個運算符,*p是對指針p進行運算——在等號右邊的話,意思是「讀取p這個地址指向的值」;在等號左邊的話,意思是「把p指向的那個值所在的存儲空間拿來,要存新東西」。

我佛慈悲。


C語言裡面有一個萬能指針(void指針)你完全可以指向任意的空間,用的時候按照你喜歡的方式來用。為什麼要把它轉換為我們需要的類型呢?因為:目前的編譯器不能自動幫我們識別是什麼類型不同的類型存儲空間是不一樣的,所以我們需要手動來寫明類型


難道語言的設計不是為了讓愚蠢的人類更容易讀懂和理解和操作么。


但是指針是一個存放內存地址的變數, 在內存編址中地址都是整數,

不是

都是整數那聲明的時候為什麼不可以直接 *p = "hello", *p = 1234; 呢?

類型也意味著運算規則

對指針做*運算得到的結果不同,甚至有時根本不能對指針進行*運算


有些數據類型佔用的位元組不同


如果不區別的話,如何實現+1操作。


理論上,void *,針織int足矣

這麼寫,主要是為了可讀性,另外編譯器可以順便幫你檢查檢查類型什麼的


程序語言除了實現功能,還要易於使用,減少出錯可能。


指針有兩種語義

一是內存的基地址,

二是指向數據的類型,也就是指向單位的大小是多少。(void*除外)

如果沒有第二點,你面對的就是一堆位元組而已。


指針所指數據類型定義了指針偏移值的單位。如果指針偏移全部用位元組的類型的話,那就同彙編了,會搞得很複雜,失去了高級語言的直觀性。


不區別的話,怎麼知道要訪問幾個內存單元呢?

char 訪問一個

int 訪問四個

double 等等


為了作地址算術。


指針加減時,步長不同


推薦閱讀:

怎樣判斷浮點數是否相等並保證同一性?
對於一個很複雜的常量表達式,編譯器會算出結果再編譯嗎?
面向對象和面向過程分別是什麼?
C C++ Python哪個更適合新手?
為什麼編程語言中,循環計數器的默認變數都是「i」?

TAG:編程語言 | C編程語言 |