1. 程式人生 > >【c語言】帶你真正走進指標的世界——那些一不小心就會出現的BUG

【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 ] 是從常量區中把資料複製過來後再進行修改,所以可以正常執行!