【c語言】帶你真正走進指標的世界——那些一不小心就會出現的BUG
Let's go ~
程式碼如下
#include <stdio.h>
int main()
{
int a = 3,b = 3;
(a = 0) && (b = 5);
printf("a = %d,b = %d\n",a,b);
(a = 1) || (b = 5);
printf("a = %d,b = %d\n",a,b);
return 0;
}
注:(1) 邏輯運算子 “&&” 代表的是兩邊同時為 “ 1 ” 時才輸出 “ 真 ” ,任意一邊為 “ 0 ” 輸出都為 " 假 "。而在編譯器裡,程式碼是按照從左到右的順序編譯的,所以當程式編譯到“ (a = 0)” 時,即左邊結果為 “ 0 ”,所以直接輸出 “ 假 ”,不再編譯右邊的 “(b = 5)”,所以最終結果為: a=0,b=3.
(2) 邏輯運算子 “||” 代表的是隻要兩邊任意一邊的結果為“ 1 ”時,即輸出結果“ 真 ”。而在編譯器裡,程式碼是按照從左到右的順序編譯的,所以當程式編譯到“ (a = 1)” 時,即左邊結果為 “ 1 ”,所以直接輸出 “ 真 ”,不再編譯右邊的 “(b = 5)”,所以最終結果為: a=1,b=3.
程式碼如下
#include <stdio.h>
#include <string.h>
int main()
{
char* str = "I Love You";
int length = strlen(str);
for(int i=0;i<length;i++)
{
printf("%c",str[i]);
}
if(i == length)
printf("\n");
return 0;
}
???給一個指標賦值一串字元???
???列印指標還可以用陣列的方式打印出來???
???這究竟是神馬???
注:指標和陣列有很多相似的地方,其中之一就是:陣列的變數名代表的是陣列第一個變數的地址(陣列的首地址),所以陣列名其實也算是一個指標,指向的是第一個陣列的地址,而我們平常使用的是陣列的常規用法,而例如上面程式碼所寫的用指標來建立一個字元陣列是正規用法。
程式碼 如下
#include <stdio.h>
#include <string.h>
int main()
{
char* x = "china";
char y[] = "china";
*(x+1) = 'A';
y[1] = 'A';
return 0;
}
程式雖然沒有報錯,但是執行就會奔潰,單步除錯可以發現,是因為擅自修改不可修改的記憶體導致的
在回答問題前我們先了解下記憶體的結構分割槽
由圖可知,在記憶體的分佈中,存放常量的區域是 可讀不可寫 的,意思是“可以讀取出去,但是不能寫入進來”
然後我們再來看看例子程式碼的記憶體分佈
由圖上可知,給型別為char* 的變數賦值時,是從變數區直接賦值過來的,而給型別為char 陣列賦值時,是從變數區中複製過來的!!!
注:簡單來說,如果把 ‘ A ’ 賦值給char* 和char 型別的話
*(x + 1) 是直接修改了常量區的資料,結合 圖上 “變數區可讀不可寫” 的原則,將會導致記憶體擅自讀寫而程式奔潰。
y[ 1 ] 是從常量區中把資料複製過來後再進行修改,所以可以正常執行!