當前位置:首頁 » 編程語言 » c語言中指針加減問題求解
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言中指針加減問題求解

發布時間: 2022-02-28 02:39:05

1. c語言指針相減報錯的問題

C語言數組和指針的理解_在取地址運算上的操作_指針加減操作_a 和&a 的區別

1.一個實例+理論分析

在了解數組和指針的訪問方式前提下,下面再看這個例子:

123456main(){inta[5]={1,2,3,4,5};int*ptr=(int*)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));}

列印出來的值為多少呢? 這里主要是考查關於指針加減操作的理解。


對指針進行加1操作,得到的是下一個元素的地址,而不是原有地址值直接加1。所 以,一個類型為T的指針的移動,以sizeof(T) 為移動單位。

因此,對上題來說,a是一個一維數組,數組中有5個元素,所以a的類型是數組指針;ptr是一個int 型的指針,ptr的類型是整型指針。

1&a +1:取數組a 的首地址,該地址的值加上sizeof(a) 的值,即&a +5*sizeof(int),也就是下一個數組的首地址。

顯然當前指針已經越過了數組的界限。


(int *)(&a+1): 則是把上一步計算出來的地址,強制轉換為int * 類型,賦值給ptr。

*(a+1):a,&a的值是一樣的,但意思不一樣,a是數組首元素的首地址,也就是a[0]的首地址,&a是數組的首地址,a+1是數組下一元素的首地址,即a[1]的首地址,&a+1是下一個數組的首地址。

所以輸出2*(ptr-1):因為ptr是指向a[5],並且ptr是int * 類型,所以*(ptr-1)是指向a[4],輸出5。

2.Visual C++6.0上的真實調試結果


這些分析我相信大家都能理解,但是在授課時,學生向我(陳正沖老師)提出了如下問題:


在Visual C++6.0的Watch窗口中&a+1的值怎麼會是(x0012ff6d(0x0012ff6c+1)呢?

上圖是在Visual C++6.0調試本函數時的截圖。

123a在這里代表是的數組首元素的地址即a[0]的首地址,其值為0x0012ff6c。&a代表的是數組的首地址,其值為0x0012ff6c。a+1的值是0x0012ff6c+1*sizeof(int),等於0x0012ff70。


問題就是&a+1的值怎麼會是(x0012ff6d(0x0012ff6c+1)呢?


按照我們上面的分析應該為0x0012ff6c+5*sizeof(int)。其實很好理解。當你把&a+1放到Watch窗口中觀察其值時,表達式&a+1已經脫離其上下文環境,編譯器就很簡單的把它解析為&a的值然後加上1byte。而a+1的解析就正確,我(陳正沖老師)認為這是Visual C++6.0的一個bug。既然如此,我們怎麼證明證明&a+1的值確實為0x0012ff6c+5*sizeof(int)呢?

很好辦,用printf函數列印出來。這就是我在本書前言里所說的,有的時候我們確實需要printf函數才能解決問題。你可以試試用printf("%x",&a+1);列印其值,看是否為0x0012ff6c+5*sizeof(int)。注意如果你用的是printf("%d",&a+1);列印,那你必須在十進制和十六進制之間換算一下,不要冤枉了編譯器。

另外我(陳正沖老師)要強調一點:不到非不得已,盡量別使用printf函數,它會使你養成只看結果不問為什麼的習慣。比如這個列子,*(a+1)和*(ptr-1)的值完全可以通過Watch窗口來查看。平時初學者很喜歡用「printf("%d,%d",*(a+1),*(ptr-1));」這類的表達式來直接列印出值,如果發現值是正確的就歡天喜地。這個時候往往認為自己的代碼沒有問題,根本就不去查看其變數的值,更別說是內存和寄存器的值了。(嗯,這個壞習慣,我是有的。)

3. 最好不要利用printf函數進行調試

陳正沖老師的經驗與教誨:

更有甚者,printf函數列印出來的值不正確,就措手無策,舉手問「老師,我這里為什麼不對啊?」。長此以往就養成了很不好的習慣,只看結果,不重調試。這就是為什麼同樣的幾年經驗,有的人水平很高,而有的人水平卻很低。其根本原因就在於此,往往被一些表面現象所迷惑。printf函數列印出來的值是對的就能說明你的代碼一定沒問題嗎?我看未必。曾經一個學生,我讓其實現直接插入排序演算法。很快他把函數寫完了,把值用printf函數列印出來給我看。我看其代碼卻發現他使用的演算法本質上其實是冒泡排序,只是寫得像直接插入排序罷了。等等這種情況數都數不過來,往往犯了錯誤還以為自己是對的。所以我平時上課之前往往會強調,不到非不得已,不允許使用printf函數,而要自己去查看變數和內存的值。學生的這種不好的習慣也與目前市面上的教材、參考書有關,這些書甚至花大篇幅來介紹scanf和printf這類的函數,卻幾乎不講解調試技術。甚至有的書還在講TruboC 2.0之類的調試器!如此教材教出來的學生質量可想而知。

2. C語言指針運算問題

*q++

*(q++)是一樣的
沒錯,括弧是會提高優先順序,但是對於q++這個自加運算是沒有作用的.後置的++做自加運算都是等當前語句處理完了才自加1的.所以*(q++)可以看成是
*(q);
q=q+1;
可以看出括弧只括著q...這樣的括弧其實是並沒有提高任何優先順序的...

3. c語言指針變數之間可以進行加減運算

可以啊指針其實也是一個內存單元,存放了一個地址,變數也是一個內存單元,存放了一個變數。減了就是吧指針這個內存單雲存放的地址減了。

4. C語言兩個指針相減的問題

雖然地址是隨機的,因為數組從首地址開始依次相連


#include<stdio.h>
intmain()
{
chara[10];
char*b=&a[2];
char*p=&a[8];
printf("a[0]=%d ",&a[0]);//若a[0]地址為1000
printf("a[10]=%d ",&a[10]);//a[10]的地址就為1000+10
printf("a[2]=%d ",&a[2]);//所以a[2]為1000+2
printf("a[8]=%d ",&a[8]);//a[8]為1000+8
printf("%d",b-p);//a[2]-a[8]就等於1002-1008=-6
return0;
}

看看這段代碼,希望能幫助你,望採納

5. C語言 指針的減法 小問題

數組名 就代表數組的首地址,相當於一個地址常量
char *p=str; 這句是定義一個指針變數p,並將str的值(地址)賦值給p,這樣p就指向str所在的數據了。

這句表示兩層意思
1、char *p ; 定義指針變數
2、p=str;注意不是*p=str! 將str值賦值給p
是指針定義並初始化的樣子。

6. C語言數組指針相減問題

age+1-age=1;
這里的1就是單純的數字1,沒有別的含義,所以結果是1

而第二個就不同了
(int)(age+1)-(int)(age)=4
這里加1是指,指針向後移動一個單位,單位是多少呢?
由於定義的是int型,在32位機中,int佔4個位元組,即一個單位=4位元組

樓主若還不清楚,可以hi我

7. 關於c語言中的指針運算問題,求指教

#include<stdio.h>
main()
{
int k=2,m=4,n=6,*pk=&k,*pm=&m,*p;
p=&n ; //&是取變數地址的操作符,本句意思是將變數n所在的地址存儲在p中。pm,pk同理。
*p=*pk * (*pm); //*是操作地址單元的操作符,*p就是相當於使用n(因為p是n的地址) , 同理pk , pm
printf("%d\n",n); //n=k*m=2*4=8 ;原來的6被覆蓋了
}

8. 計算機c語言,指針與整數的加減法問題,

因為double是雙精度類型,站8個位元組。所以是5*8
滿意請採納! 追問可是書上寫著佔4個位元組~~
這個根據你的CPU和系統來決定

9. c語言中指針加減問題,求解答。

首先:
float
a[10],*p,*q;
p=&a[4],q=&a[7];
那q-p=2(a[4]與a[7]之間有兩個元素)
***這里就不對了,q-p
=
3
不是等於2,
可以用printf("%d",q-p);看看。
p+3-p
=
12
是地址按「位元組」排列的位置差,表示p+3和p之間有12個位元組
q-p
=
3
表示q和p之間有3個float類型的數據,每個佔4位元組,3x4
=
12
和上面的結果一致

10. 一個C語言指針自增自減的問題

如果放在第三個位置的話,那要等循環執行一次之後才會執行這個指針自減
出現那些數字,是因為在執行完上一個 for 循環之後,Ptr 已經到了數組外面去了,當然就會有隨機數出來,那是其他內存區域的數據