看到一篇關于C語言指標的文章,正好最近在看《C和指標》就去看了一下。《一道 C 語言指標訪存題目的引申》,里面的第一個題目就把我難住了。
幫助123456789 #include <stdio.h> int main() { int a[5] = {1, 2, 3, 4, 5}; int *pa = (int)(&a) + 1; printf("%x\n", *pa); return 0; }
正確的輸出結果應該是 2000000.自詡對C指標還比較了解,不就是保存記憶體地址的變數嗎?有什么難的,后來才發現我錯了。我想的是&a,是對陣列名字去地址,那出來的結果不就是保存a的地址,那這樣給他轉換成int變數之后再加1,然后再賦值給一個int*指標是會出錯的,結果我編譯了一下,真的出錯了:
error: invalid conversion from `int' to `int*'.
無法將int值賦值給int *指標變數,我修改了一下,在(int)(&a) + 1;前面加上了一個強制型別轉換 (int *),編譯之后輸出結果:
我以為正確了,雖然他說正確答案是 2000000。后來我又仔細看了一下源代碼,發現 int *pa = (int *)(int)(&a) + 1; 這句代碼是先將 &a 轉換成指標再在其基礎加 1。而原來的意思是先給 &a 加 1再轉換成指標,結果我再修改了一下代碼:int *pa = (int *)((int)(&a) + 1); 這樣結果竟然正確了,輸出2000000:
這時候我完全朦了,這是怎么回事?后來我將 &a 和 a作為整數輸出,想看看它到底是什么,結果發現
幫助12 printf("%d\n",&a); printf("%d\n",a);
他們的輸出結果是一樣的,也就是說a 和 &a 的值一樣,我以為問題到這里就解決了,但是我還是不能理解為什么會輸出 2000000.于是我到網上去搜索了一下資料,結果搜到了 對陣列名取地址是什么? 。里面說
“
幫助123 1 int array[100]; 3 memset(array, 0, sizeof(array)); 4 memset(&array, 0, sizeof(array));
第3行和第4行有什么不同嗎?其實從效果上來說是一樣的,但是這里要注意 array 和 &array 的型別是不同的。array 相當于 &array[0],而 &array 是一個指向 int[100] 的指標,型別是 int(*)[100]。”
總算知道了a和&a的差別,但是我還是不明白為什么它會輸出 2000000,這到底是為什么呢?
我試著修改了一下代碼:
int a[] = {1,5};
這樣之后的輸出結果成了 : 5000000 原來和陣列a的第二個元素有關系。哈哈,有點懂了,經過我N次的試驗。
首先我們的代碼是:
幫助123 int a[] = {1,2}; int *pa = (int *)((int)(&a) + 1); printf("%x\n", *(pa));
我這邊編譯的結果 a[0]也就是a代表的地址是 0x22ff70 a[1] 的地址是 0x22ff74 。我查看了一下記憶體(使用printf看的),記憶體里的資料是這樣的:
幫助12 0x22ff70 0x22ff71 ... 0x22ff74 ... 0x22ff77 01 00 ... 02 ... 00
而且我們知道訪問記憶體中的資料是高位元組的地址是高位,低位元組的地址是低位。也就是說如果我的地址是 0x22ff70,以這個地址訪問一個整數,得到的整數就是73,72,71,70的資料排列 即00000001(以前學過一點匯編,加上自己試驗了一下,就出來的 :),也就是1。如果訪問0x22ff74 也就是 00000002 是2.如果訪問 0x22ff71 也就是從74開始 02000000。這不就是我們的正確答案 2000000 。
問題解決!寫得比較亂,勿怪。若有錯誤,歡迎指正!
(全文完)
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
分析的很好 不過這個貌似沒什么實用價值...uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
你咋發到問題里來了,應該自己開博客發到里面uj5u.com熱心網友回復:
試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看試試看uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
每天回帖即可獲得10分可用分!uj5u.com熱心網友回復:
學習受用了!~~uj5u.com熱心網友回復:
學習受用了!~~uj5u.com熱心網友回復:
學習受用了!~~uj5u.com熱心網友回復:
收益了
uj5u.com熱心網友回復:
學習了
uj5u.com熱心網友回復:
回帖賺積分。。uj5u.com熱心網友回復:
不錯,牛人,學習了!!!uj5u.com熱心網友回復:
學習了指標這東西比較復雜
uj5u.com熱心網友回復:
受教了
uj5u.com熱心網友回復:
以前從沒注意到arr和&arr 不過語法上來講都行的通uj5u.com熱心網友回復:
語法上來講都行的通uj5u.com熱心網友回復:
受教了
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
踩一下,留個名uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
回帖賺積分。。uj5u.com熱心網友回復:
路過看看。。uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
每天回帖即可獲得10分可用分!uj5u.com熱心網友回復:
計算機組成原理→DOS命令→匯編語言→C語言(不包括C++)、代碼書寫規范→資料結構、編譯原理、作業系統→計算機網路、資料庫原理、正則運算式→其它語言(包括C++)、架構……對學習編程者的忠告:
眼過千遍不如手過一遍!
書看千行不如手敲一行!
手敲千行不如單步一行!
單步源代碼千行不如單步對應匯編一行!
VC除錯時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
對VC來說,所謂‘除錯時’就是編譯連接通過以后,按F10或F11鍵單步執行一步以后的時候,或者在某行按F9設了斷點后按F5執行停在該斷點處的時候。
(Turbo C或Borland C用Turbo Debugger除錯,Linux或Unix下用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習匯編以及C和匯編的對應關系。
從匯編的角度理解和學習C語言的指標,原本看似復雜的東西就會變得非常簡單!
指標即地址。“地址又是啥?”“只能從匯編語言和計算機組成原理的角度去解釋了。”
但我又不得不承認:
有那么些人喜歡或者適合用“先具體再抽象”的方法學習和理解復雜事物;
而另一些人喜歡或者適合用“先抽象再具體”的方法學習和理解復雜事物。
而我本人屬前者。
不要企圖依賴輸出指標相關運算式的值【比如printf("%p\n",...)】來理解指標的本質,
而要依賴除錯時的反匯編視窗中的C/C++代碼【比如void *p=...】及其對應匯編指令以及記憶體視窗中的記憶體地址和記憶體值來理解指標的本質。
這輩子不看記憶體地址和記憶體值;只畫鏈表、指標示意圖,畫堆疊示意圖,畫各種示意圖,甚至自己沒畫過而只看過書上的圖……能從本質上理解指標、理解函式引數傳遞嗎?本人深表懷疑!
這輩子不種麥不收麥不將麥粒拿去磨面;只吃饅頭、吃面條、吃面包、……甚至從沒看過別人怎么蒸饅頭,壓面條,烤面包,……能從本質上理解面粉、理解面食嗎?本人深表懷疑!!
提醒:
“學習用匯編語言寫程式”
和
“VC除錯(TC或BC用TD除錯)時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
(Linux或Unix下可以在用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習C和匯編的對應關系。”
不是一回事!
不要迷信書、考題、老師、回帖;
要迷信CPU、編譯器、除錯器、運行結果。
并請結合“盲人摸太陽”和“駕船出海時一定只帶一個指南針。”加以理解。
任何理論、權威、傳說、真理、標準、解釋、想象、知識……都比不上擺在眼前的事實!
有人說一套做一套,你相信他說的還是相信他做的?
其實嚴格來說這個世界上古往今來所有人都是說一套做一套,不是嗎?
不要寫連自己也預測不了結果的代碼!
電腦記憶體或檔案內容只是一個一維二進制位元組陣列及其對應的二進制地址;
人腦才將電腦記憶體或檔案內容中的這個一維二進制位元組陣列及其對應的二進制地址的某些部分看成是整數、有符號數/無符號數、浮點數、復數、英文字母、阿拉伯數字、中文/韓文/法文……字符/字串、匯編指令、函式、函式引數、堆、堆疊、陣列、指標、陣列指標、指標陣列、陣列的陣列、指標的指標、二維陣列、字符點陣、字符筆畫的坐標、黑白二值圖片、灰度圖片、彩色圖片、錄音、視頻、指紋資訊、身份證資訊……
十字鏈表交換任意兩個節點C源代碼(C指標應用終極挑戰)http://download.csdn.net/detail/zhao4zhong1/5532495
uj5u.com熱心網友回復:

不明覺歷
arr 和&arr的區別主要就是做整數加法的時候
int arr[2];
arr + 1 和 &arr + 1,二者對1的偏移解釋不一樣,就是這么簡單,沒什么可糾結的
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
學習了
uj5u.com熱心網友回復:
a和&a取地址 是有一定區別的,29樓簡單化了~uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
C 太難了,俺passuj5u.com熱心網友回復:
無聊的考試題, 為什么要寫這樣的代碼呢?uj5u.com熱心網友回復:
不明覺厲 int * +1 和 int +1 考慮大小端大概就這樣吧。uj5u.com熱心網友回復:
支持一個
uj5u.com熱心網友回復:
樓主寫了這么多,我來總結下吧。陣列a存盤的內容,按20個位元組(小端模式)分別為:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
其中a指向01開始處
int *pa = (int *)((int)(&a) + 1);
這里pa相比a地址,增加一個位元組,指向01后面的00,所以int *pa表示的內容為00 00 00 02,printf出來就是2000000
int *pc = a + 1;
這里pc指向02開始處,int *pc表示的內容為02 00 00 00,printf出來就是00 00 00 02
int *pb = (int *)&a + 1;
這里pb指向陣列a越界的地方a[5],int *pb表示的內容為記憶體未初始化的值。
uj5u.com熱心網友回復:
學習了。。。uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
你回答問題的時候能不能不加那么多無關的東西啊,跟水經驗一樣uj5u.com熱心網友回復:
簡潔多了。。。uj5u.com熱心網友回復:
我也是菜鳥,不過至少認真一點這個問題還是挺簡單的,陣列名稱也是一個指標,有一種說法是陣列名稱是一個指標常量就是說他是一個常量,本質上。。。那個常量的值是陣列的首地址,既是陣列第一個元素的地址
一般寫a 陣列名就行了,沒必要再寫取地址運算子,比如 int a[5] = {0}; scanf("%d",a); 而不是scanf("%d",&a);
雖然那第二個代碼沒錯,但是一般來說沒必要&了,字太長懶得看了,嘿嘿。。
uj5u.com熱心網友回復:
好好學習,天天向上
uj5u.com熱心網友回復:
每天回帖即可獲得10分可用分!uj5u.com熱心網友回復:
這就是苦口婆心啊。
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
樓主寫了這么多,我來總結下吧。
陣列a存盤的內容,按20個位元組(小端模式)分別為:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
其中a指向01開始處
int *pa = (int *)((int)(&a) + 1);
這里pa相比a地址,增加一個位元組,指向01后面的00,所以int *pa表示的內容為00 00 00 02,printf出來就是2000000
int *pc = a + 1;
這里pc指向02開始處,int *pc表示的內容為02 00 00 00,printf出來就是00 00 00 02
int *pb = (int *)&a + 1;
這里pb指向陣列a越界的地方a[5],int *pb表示的內容為記憶體未初始化的值。
最后一個有問題int *pb = (int *)&a + 1;這個指向的是a[1], (int*)(&a+1)這個才是越界
uj5u.com熱心網友回復:
你回答問題的時候能不能不加那么多無關的東西啊,跟水經驗一樣
計算機組成原理→DOS命令→匯編語言→C語言(不包括C++)、代碼書寫規范→資料結構、編譯原理、作業系統→計算機網路、資料庫原理、正則運算式→其它語言(包括C++)、架構……
對學習編程者的忠告:
眼過千遍不如手過一遍!
書看千行不如手敲一行!
手敲千行不如單步一行!
單步源代碼千行不如單步對應匯編一行!
VC除錯時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
對VC來說,所謂‘除錯時’就是編譯連接通過以后,按F10或F11鍵單步執行一步以后的時候,或者在某行按F9設了斷點后按F5執行停在該斷點處的時候。
(Turbo C或Borland C用Turbo Debugger除錯,Linux或Unix下用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習匯編以及C和匯編的對應關系。
從匯編的角度理解和學習C語言的指標,原本看似復雜的東西就會變得非常簡單!
指標即地址。“地址又是啥?”“只能從匯編語言和計算機組成原理的角度去解釋了。”
但我又不得不承認:
有那么些人喜歡或者適合用“先具體再抽象”的方法學習和理解復雜事物;
而另一些人喜歡或者適合用“先抽象再具體”的方法學習和理解復雜事物。
而我本人屬前者。
不要企圖依賴輸出指標相關運算式的值【比如printf("%p\n",...)】來理解指標的本質,
而要依賴除錯時的反匯編視窗中的C/C++代碼【比如void *p=...】及其對應匯編指令以及記憶體視窗中的記憶體地址和記憶體值來理解指標的本質。
這輩子不看記憶體地址和記憶體值;只畫鏈表、指標示意圖,畫堆疊示意圖,畫各種示意圖,甚至自己沒畫過而只看過書上的圖……能從本質上理解指標、理解函式引數傳遞嗎?本人深表懷疑!
這輩子不種麥不收麥不將麥粒拿去磨面;只吃饅頭、吃面條、吃面包、……甚至從沒看過別人怎么蒸饅頭,壓面條,烤面包,……能從本質上理解面粉、理解面食嗎?本人深表懷疑!!
提醒:
“學習用匯編語言寫程式”
和
“VC除錯(TC或BC用TD除錯)時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
(Linux或Unix下可以在用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習C和匯編的對應關系。”
不是一回事!
不要迷信書、考題、老師、回帖;
要迷信CPU、編譯器、除錯器、運行結果。
并請結合“盲人摸太陽”和“駕船出海時一定只帶一個指南針。”加以理解。
任何理論、權威、傳說、真理、標準、解釋、想象、知識……都比不上擺在眼前的事實!
有人說一套做一套,你相信他說的還是相信他做的?
其實嚴格來說這個世界上古往今來所有人都是說一套做一套,不是嗎?
不要寫連自己也預測不了結果的代碼!
電腦記憶體或檔案內容只是一個一維二進制位元組陣列及其對應的二進制地址;
人腦才將電腦記憶體或檔案內容中的這個一維二進制位元組陣列及其對應的二進制地址的某些部分看成是整數、有符號數/無符號數、浮點數、復數、英文字母、阿拉伯數字、中文/韓文/法文……字符/字串、匯編指令、函式、函式引數、堆、堆疊、陣列、指標、陣列指標、指標陣列、陣列的陣列、指標的指標、二維陣列、字符點陣、字符筆畫的坐標、黑白二值圖片、灰度圖片、彩色圖片、錄音、視頻、指紋資訊、身份證資訊……
十字鏈表交換任意兩個節點C源代碼(C指標應用終極挑戰)http://download.csdn.net/detail/zhao4zhong1/5532495
這就是苦口婆心啊。
uj5u.com熱心網友回復:
不明覺厲,c指標真是讓人頭疼uj5u.com熱心網友回復:
int *pa = (int *)((int)(&a) + 1);(int)(&a)這個表示什么意思呢?
uj5u.com熱心網友回復:
學習了
uj5u.com熱心網友回復:
學習中~~謝謝分享uj5u.com熱心網友回復:
一直被指標的問題困擾,還請多指教
uj5u.com熱心網友回復:
a和&a取地址 是有一定區別的,29樓簡單化了~
一語中的。。做了個實驗 就是指標沒有向4地址對齊導致的。。
uj5u.com熱心網友回復:
計算機組成原理→DOS命令→匯編語言→C語言(不包括C++)、代碼書寫規范→資料結構、編譯原理、作業系統→計算機網路、資料庫原理、正則運算式→其它語言(包括C++)、架構……
對學習編程者的忠告:
眼過千遍不如手過一遍!
書看千行不如手敲一行!
手敲千行不如單步一行!
單步源代碼千行不如單步對應匯編一行!
VC除錯時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
對VC來說,所謂‘除錯時’就是編譯連接通過以后,按F10或F11鍵單步執行一步以后的時候,或者在某行按F9設了斷點后按F5執行停在該斷點處的時候。
(Turbo C或Borland C用Turbo Debugger除錯,Linux或Unix下用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習匯編以及C和匯編的對應關系。
從匯編的角度理解和學習C語言的指標,原本看似復雜的東西就會變得非常簡單!
指標即地址。“地址又是啥?”“只能從匯編語言和計算機組成原理的角度去解釋了。”
但我又不得不承認:
有那么些人喜歡或者適合用“先具體再抽象”的方法學習和理解復雜事物;
而另一些人喜歡或者適合用“先抽象再具體”的方法學習和理解復雜事物。
而我本人屬前者。
不要企圖依賴輸出指標相關運算式的值【比如printf("%p\n",...)】來理解指標的本質,
而要依賴除錯時的反匯編視窗中的C/C++代碼【比如void *p=...】及其對應匯編指令以及記憶體視窗中的記憶體地址和記憶體值來理解指標的本質。
這輩子不看記憶體地址和記憶體值;只畫鏈表、指標示意圖,畫堆疊示意圖,畫各種示意圖,甚至自己沒畫過而只看過書上的圖……能從本質上理解指標、理解函式引數傳遞嗎?本人深表懷疑!
這輩子不種麥不收麥不將麥粒拿去磨面;只吃饅頭、吃面條、吃面包、……甚至從沒看過別人怎么蒸饅頭,壓面條,烤面包,……能從本質上理解面粉、理解面食嗎?本人深表懷疑!!
提醒:
“學習用匯編語言寫程式”
和
“VC除錯(TC或BC用TD除錯)時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
(Linux或Unix下可以在用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習C和匯編的對應關系。”
不是一回事!
不要迷信書、考題、老師、回帖;
要迷信CPU、編譯器、除錯器、運行結果。
并請結合“盲人摸太陽”和“駕船出海時一定只帶一個指南針。”加以理解。
任何理論、權威、傳說、真理、標準、解釋、想象、知識……都比不上擺在眼前的事實!
有人說一套做一套,你相信他說的還是相信他做的?
其實嚴格來說這個世界上古往今來所有人都是說一套做一套,不是嗎?
不要寫連自己也預測不了結果的代碼!
電腦記憶體或檔案內容只是一個一維二進制位元組陣列及其對應的二進制地址;
人腦才將電腦記憶體或檔案內容中的這個一維二進制位元組陣列及其對應的二進制地址的某些部分看成是整數、有符號數/無符號數、浮點數、復數、英文字母、阿拉伯數字、中文/韓文/法文……字符/字串、匯編指令、函式、函式引數、堆、堆疊、陣列、指標、陣列指標、指標陣列、陣列的陣列、指標的指標、二維陣列、字符點陣、字符筆畫的坐標、黑白二值圖片、灰度圖片、彩色圖片、錄音、視頻、指紋資訊、身份證資訊……
十字鏈表交換任意兩個節點C源代碼(C指標應用終極挑戰)http://download.csdn.net/detail/zhao4zhong1/5532495
話說我在哪都看到你灌水...
而且都是又臭又長.
有一些壓根就對不上題.......
uj5u.com熱心網友回復:
int *pa = (int *)((int)(&a) + 1);
(int)(&a)這個表示什么意思呢?
把a的地址轉換成了int, 此時在+1 不過是int + 1, 不是int *更不是 int *[5];
uj5u.com熱心網友回復:
計算機組成原理→DOS命令→匯編語言→C語言(不包括C++)、代碼書寫規范→資料結構、編譯原理、作業系統→計算機網路、資料庫原理、正則運算式→其它語言(包括C++)、架構……
對學習編程者的忠告:
眼過千遍不如手過一遍!
書看千行不如手敲一行!
手敲千行不如單步一行!
單步源代碼千行不如單步對應匯編一行!
VC除錯時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
對VC來說,所謂‘除錯時’就是編譯連接通過以后,按F10或F11鍵單步執行一步以后的時候,或者在某行按F9設了斷點后按F5執行停在該斷點處的時候。
(Turbo C或Borland C用Turbo Debugger除錯,Linux或Unix下用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習匯編以及C和匯編的對應關系。
從匯編的角度理解和學習C語言的指標,原本看似復雜的東西就會變得非常簡單!
指標即地址。“地址又是啥?”“只能從匯編語言和計算機組成原理的角度去解釋了。”
但我又不得不承認:
有那么些人喜歡或者適合用“先具體再抽象”的方法學習和理解復雜事物;
而另一些人喜歡或者適合用“先抽象再具體”的方法學習和理解復雜事物。
而我本人屬前者。
不要企圖依賴輸出指標相關運算式的值【比如printf("%p\n",...)】來理解指標的本質,
而要依賴除錯時的反匯編視窗中的C/C++代碼【比如void *p=...】及其對應匯編指令以及記憶體視窗中的記憶體地址和記憶體值來理解指標的本質。
這輩子不看記憶體地址和記憶體值;只畫鏈表、指標示意圖,畫堆疊示意圖,畫各種示意圖,甚至自己沒畫過而只看過書上的圖……能從本質上理解指標、理解函式引數傳遞嗎?本人深表懷疑!
這輩子不種麥不收麥不將麥粒拿去磨面;只吃饅頭、吃面條、吃面包、……甚至從沒看過別人怎么蒸饅頭,壓面條,烤面包,……能從本質上理解面粉、理解面食嗎?本人深表懷疑!!
提醒:
“學習用匯編語言寫程式”
和
“VC除錯(TC或BC用TD除錯)時按Alt+8、Alt+7、Alt+6和Alt+5,打開匯編視窗、堆疊視窗、記憶體視窗和暫存器視窗看每句C對應的匯編、單步執行并觀察相應堆疊、記憶體和暫存器變化,這樣過一遍不就啥都明白了嗎。
(Linux或Unix下可以在用GDB除錯時,看每句C對應的匯編并單步執行觀察相應記憶體和暫存器變化。)
想要從本質上理解C指標,必須學習C和匯編的對應關系。”
不是一回事!
不要迷信書、考題、老師、回帖;
要迷信CPU、編譯器、除錯器、運行結果。
并請結合“盲人摸太陽”和“駕船出海時一定只帶一個指南針。”加以理解。
任何理論、權威、傳說、真理、標準、解釋、想象、知識……都比不上擺在眼前的事實!
有人說一套做一套,你相信他說的還是相信他做的?
其實嚴格來說這個世界上古往今來所有人都是說一套做一套,不是嗎?
不要寫連自己也預測不了結果的代碼!
電腦記憶體或檔案內容只是一個一維二進制位元組陣列及其對應的二進制地址;
人腦才將電腦記憶體或檔案內容中的這個一維二進制位元組陣列及其對應的二進制地址的某些部分看成是整數、有符號數/無符號數、浮點數、復數、英文字母、阿拉伯數字、中文/韓文/法文……字符/字串、匯編指令、函式、函式引數、堆、堆疊、陣列、指標、陣列指標、指標陣列、陣列的陣列、指標的指標、二維陣列、字符點陣、字符筆畫的坐標、黑白二值圖片、灰度圖片、彩色圖片、錄音、視頻、指紋資訊、身份證資訊……
十字鏈表交換任意兩個節點C源代碼(C指標應用終極挑戰)http://download.csdn.net/detail/zhao4zhong1/5532495
話說我在哪都看到你灌水...
而且都是又臭又長.
有一些壓根就對不上題.......
農夫山泉和自來水都是水。
uj5u.com熱心網友回復:
GCC segmentation fault..............test code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
int array[5] = {1,2,3,4,5};
*p = (int*)((int)(&array)+1);
printf("%x",*p);
return 0;
}
這種變數都不初始化,亂用指標秀技巧的東西有什么用。。。。
規范編碼就是了
反正我這里報錯,根本就不允許上面代碼的情況出現
測驗環境:
linux
編譯器:
gcc
uj5u.com熱心網友回復:
GCC segmentation fault..............
test code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
int array[5] = {1,2,3,4,5};
*p = (int*)((int)(&array)+1);
printf("%x",*p);
return 0;
}
這種變數都不初始化,亂用指標秀技巧的東西有什么用。。。。
規范編碼就是了
反正我這里報錯,根本就不允許上面代碼的情況出現
測驗環境:
linux
編譯器:
gcc
你都抄錯了代碼。。。
uj5u.com熱心網友回復:
GCC segmentation fault..............
test code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
int array[5] = {1,2,3,4,5};
*p = (int*)((int)(&array)+1);
printf("%x",*p);
return 0;
}
這種變數都不初始化,亂用指標秀技巧的東西有什么用。。。。
規范編碼就是了
反正我這里報錯,根本就不允許上面代碼的情況出現
測驗環境:
linux
編譯器:
gcc
你都抄錯了代碼。。。
樓主寫的int *pa = (int *)((int)(&a) + 1);
我沒明白我哪兒copy錯了。我只是改了一下變數名而已
uj5u.com熱心網友回復:
不明覺歷
arr 和&arr的區別主要就是做整數加法的時候
int arr[2];
arr + 1 和 &arr + 1,二者對1的偏移解釋不一樣,就是這么簡單,沒什么可糾結的
uj5u.com熱心網友回復:
本人也是剛學的,學習學習uj5u.com熱心網友回復:
int *pa = (int *)((int)(&a) + 1);
(int)(&a)這個表示什么意思呢?
把a的地址轉換成了int, 此時在+1 不過是int + 1, 不是int *更不是 int *[5];
這個我知道。一個二進制的地址轉換成int型,然后是Int+1,然后再把這個Int轉換成指向Int的一個指標(地址),結果為什么會指向下一個陣列元素呢?這才是問題的關鍵。
uj5u.com熱心網友回復:
int *pa = (int *)((int)(&a) + 1);
(int)(&a)這個表示什么意思呢?
把a的地址轉換成了int, 此時在+1 不過是int + 1, 不是int *更不是 int *[5];
這個我知道。一個二進制的地址轉換成int型,然后是Int+1,然后再把這個Int轉換成指向Int的一個指標(地址),結果為什么會指向下一個陣列元素呢?這才是問題的關鍵。
int一次移動4位元組,這里只移動了1位元組。
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
GCC segmentation fault..............
test code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
int array[5] = {1,2,3,4,5};
*p = (int*)((int)(&array)+1);
printf("%x",*p);
return 0;
}
這種變數都不初始化,亂用指標秀技巧的東西有什么用。。。。
規范編碼就是了
反正我這里報錯,根本就不允許上面代碼的情況出現
測驗環境:
linux
編譯器:
gcc
你都抄錯了代碼。。。
樓主寫的int *pa = (int *)((int)(&a) + 1);
我沒明白我哪兒copy錯了。我只是改了一下變數名而已
*p = (int*)((int)(&array)+1);//你把int* 賦值給你int 你覺得呢?
uj5u.com熱心網友回復:
GCC segmentation fault..............
test code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p;
int array[5] = {1,2,3,4,5};
*p = (int*)((int)(&array)+1);
printf("%x",*p);
return 0;
}
這種變數都不初始化,亂用指標秀技巧的東西有什么用。。。。
規范編碼就是了
反正我這里報錯,根本就不允許上面代碼的情況出現
測驗環境:
linux
編譯器:
gcc
你都抄錯了代碼。。。
樓主寫的int *pa = (int *)((int)(&a) + 1);
我沒明白我哪兒copy錯了。我只是改了一下變數名而已
*p = (int*)((int)(&array)+1);//你把int* 賦值給你int 你覺得呢?

我覺得你開始看過樓主的帖子再回復比較好,我只是照著LZ給出的代碼debug
uj5u.com熱心網友回復:
最后一個有問題int *pb = (int *)&a + 1;這個指向的是a[1], (int*)(&a+1)這個才是越界這個值得再討論一下。我覺得應該沒有越界。電腦上剛重做系統,不然就實驗一下。
uj5u.com熱心網友回復:
uj5u.com熱心網友回復:
牛角尖有的時候還是挺關鍵的uj5u.com熱心網友回復:
//char (*(*x[3])())[5];//x是什么型別的變數?
//
//分析C語言宣告,關鍵是搞清楚這個變數是個什么東西(函式、指標、陣列),
//是函式那么剩下的就是他的引數和回傳值,
//是指標那剩下部分是說明他指向什么,
//是陣列剩下的部分就是說明陣列的成員是什么型別。
//決議C語言宣告規則:
//從左側第一個識別符號開始,按照優先級進行結合。*表示是..的指標,const表示只讀的,volatile表示可變的,[]表示是陣列,()表示是函式。
//
//x和[3]結合說明是一個大小為3的陣列,該陣列指向了一個指標,該指標指向一個函式,該函式的無引數,回傳一個指標,該指標指向一個大小為5的char型陣列
#include <stdio.h>
#include <typeinfo.h>
char num[5];
char (*x00())[5] {
return #
}
int main() {
char (*x000)[5];//回傳值
char (*(x00)())[5];//函式原型,引數為空,回傳值為指標
char (*(*x0)())[5];//陣列的元素,是個函式指標
char (*(*x[3])())[5];//是個陣列,大小為3
x0 = x00;
x[0] = x0;
x[1] = x0;
x[2] = x0;
printf("typeid(x).name() is %s\n",typeid(x).name());
return 0;
}
//typeid(x).name() is char (* (__cdecl**)(void))[5]
uj5u.com熱心網友回復:
看一遍懂一遍,下次看到又得懵一會,書上很多代碼都是這樣額。uj5u.com熱心網友回復:
最簡單的理解,指針+1,其實地址值加的不是1而是加的指針類型大小
數字+1,就是數字+1
int iBuf[2]={1,2};
int *iP=iBuf;
iP+1 -->指向的地址應該是 &iBuf[2]
上面這句也等於 (int*)(int(iP)+4)
int(iP)+1就不是&iBuf[2]了.
uj5u.com熱心網友回復:
最簡單的理解,
指針+1,其實地址值加的不是1而是加的指針類型大小
數字+1,就是數字+1
int iBuf[2]={1,2};
int *iP=iBuf;
iP+1 -->指向的地址應該是 &iBuf[2]
上面這句也等於 (int*)(int(iP)+4)
int(iP)+1就不是&iBuf[2]了.
表述有點錯誤
指針+1,其實地址值加的不是1而是加的指針類型大小
應該為
指針+1,其實地址值加的不是1而是加的指針所對應的數據類型大小
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/139867.html
標籤:基礎類
