爲了驗證指針加減運算時是移動一個字節還是移動指針所指向數據類型的字節長度。我們用一下程序即可驗證。
1 int a = 0;
2 int* pa = &a;
3
4 printf("%d \n",(int)pa);
5 pa ++ ;
6 printf("%d \n",(int)pa);
7 printf("int %d %d \n",(int)pa,(int)(pa++));
對於char型指針,執行 pa++ 後,其地址增加1,對於int型指針,執行 pa++ 後,其地址增加4。(編程環境:32位操作系統。VS2010)
由此可知 指針加減運算移動單位爲指針所指向數據類型的字節長度。
遇到的問題 :
以上程序的輸出爲:
由第7行的輸出可知:printf入棧爲自右往左, (int)(pa++) 先將參數入棧,再++,而後在對(int)pa入棧時,之前以++過一次,所以輸出結果如上。
若將第7行代碼改爲 printf("int %d %d \n",(int)pa,(int)(++pa)); 則輸出爲 X,X+4,X+8,X+8。原理同上。
更進一步的看一個例子:
int arr[]={6,7,8,9,10};
int *ptr=arr;
printf("%d,%d,%d",*ptr,*(++ptr),*(ptr--));
在WIN32 VS2010中輸出結果爲:6,6,6
其原理爲:先執行最右邊的參數入棧,及 *(ptr),然後執行ptr- -;再執行中間參數入棧,及 ptr + +,然後*(ptr);最後執行最左邊的參數入棧,及*(ptr)。所以結果爲6,6,6.
但有人說這個執行順序與編譯器和環境相關。本人尚未測試,有興趣的可以自行測試。以上數據測試環境皆在 WIN32 VS2010中所得。如有疑問,可以共同探討。
續0:
int arr[]={6,7,8,9,10};
int *ptr=arr;
printf("%d,%d",*(++ptr),*(ptr));
同一環境下,輸出結果爲:7,7。
若 用上面的原理解釋,答案應該爲7,6。實際結果與之前解釋的相悖。求大神們指點。
續1:
若將一指針進行,強制轉換,這指針的尋址是按照原來的類型還是轉換後的類型:
char bbb[4]="0000";
int aaa = 0xf11ff22f;
int *abc = &aaa;
bbb[0] = ((char *)abc)[0];
bbb[1] = ((char *)abc)[1];
bbb[2] = ((char *)abc)[2];
bbb[3] = ((char *)abc)[3];
printf("%d %d %d %d\n",bbb[0],bbb[1],bbb[2],bbb[3]);
輸出結果:47 -14 31 -15;
以十六進制表示下列數 0x2f 0xf2 0x1f 0xf1
若將輸出改爲以十六進制輸出:
printf("%x %x %x %x\n",bbb[0],bbb[1],bbb[2],bbb[3]);
則輸出結果爲:2f fffffff2 1f fffffff1
由上結果可以知道,指針強制轉換後,尋址按照轉換以後的類型進行尋址。即 int * 變爲 char * 後,指針加1時,只移動1個字節。
對於 %x的輸出,因爲其默認爲整型數的輸出,所以負數高位全爲1,所以 -14的輸出爲 fffffff2。
在此基礎上,聯想到opencv 中IplImage的數據賦值問題。imageData指針類型爲char *;
1.對於IPL_DEPTH_8U的圖像數據來說,取值和賦值都很簡單,直接按字節進行賦值或取值即可,注意自動填充的冗餘字節數。
2.對於不是IPL_DEPTH_8U的圖像數據。例如IPL_DEPTH_16U。
當賦值時,將原始 short 類型的數據指針強制轉換爲char*,逐個字節賦值即可。
當取值時,直接將char * imageData 強制裝換爲 short * ,逐點賦值即可。