天天看點

指針知識梳理5-字元串與指針,程式記憶體總結

一、文字常量區域

#include <stdio.h>
int main()
{
	char *p = "hello";
	int i = 0;
	for(i = 0;i<6;i++)
	{
		printf("%c",*(p+i));
	}
	*p = '1';
}
           

大家分析驗證以上代碼,p 是一個指針變量,存儲位址,“hello”是一個字元串占6個位元組,當我們用printf的時候能夠輸出"hello",我們得出結論,p存儲的是存放‘h’的記憶體的位址,當我們*p = '1',去寫這塊記憶體的時候,會出現段錯誤。

根據以上現象,我們引出下面概念:

"hello"存放在 文字常量區,這個區用來存放代碼中出現的字元串常量,并且這塊記憶體區域隻能讀不能寫,以下對程式記憶體做總結:

二、程式記憶體總結

程式運作起來後分為一下幾塊記憶體區域:

1、代碼區

存放各種語句生成的指令。

2、文字常量區

字元串常量放在這裡。

比如 char *p = "hello";

3、棧區

局部變量,由系統自動申請釋放,生存周期為子產品開始到子產品結束。

4、堆區

malloc free,由程式員自己申請釋放。

5、靜态存儲區

全局變量  static 變量放在這裡,程式開始申請出來,程式結束釋放。

三、結合代碼綜合分析 

#include <stdio.h>
char a[10] = "hello"; //“hello”字元串存儲在全局數組中,在 靜态存儲區。
int main()
{
	char b[10] = "hello"; //“hello”存儲在數組b中,在棧區。
	char *p1 = "hello"; //“hello”存儲在文字常量區,p1存儲了存放‘h’的記憶體的位址,p1在棧區。
	char *p2 = NULL;//p2 在棧區
	*p = '1';//錯誤,這塊區域隻能讀。
	p2 = (char*)malloc(10);// 在堆中申請10個位元組的記憶體,并把這塊記憶體的位址存放在p2中。
	strcpy(p2,"hello");//把"hello"字元串拷貝到堆記憶體中。
	free(p2);
}
           

四、字元串操作函數的基本原理

1、printf

原型  int  printf(const char* p,...);

關于const與指針  參考 http://blog.csdn.net/xiaoliu0518/article/details/32943713

printf函數是一個可變參數函數,參數個數不定,第一個參數是const char* p ,p 存放字元串的位址,通過這個字元串的内容去解析後面的變量然後輸出相應的内容。

比如 printf("%c",...);

當字元串為"%c"的時候,printf原型可簡單了解為 printf("%c",char c),列印字元。

在比如printf("%s",...)

當字元串為"%s"的時候,printf的原型可以簡單了解為 printf("%s",const char *p),在printf中會一個一個列印字元,簡單邏輯如下:

int printf("%s",const char *p)
{
     while(*p != '\0')
     {
           putchar(*p);
           p++;
     }
}
           

是以這裡知道為什麼,%s的時候,後面可以傳char 數組、字元串常量、char* str了吧,因為形參是const char *p。

char a[10] = "hello";

printf("%s","hello");

printf("%s",a);

2、strlen 

strlen簡單邏輯如下,依然是判斷'\0'結束

int  strlen(const char *str)
{
      int len = 0;
      while(*str != '\0')
     {
          len++;
          str++;
     }
     return len;
}
           

根據形參,可以有以下調用

strlen(字元串常量)

strlen(數組名)

strlen(char*指針)

3、strcpy

strcpy簡單邏輯如下,依然是判斷'\0'結束

void strcpy(char *dest,const char* src)
{
        while(*src != '\0')
        {
		*dest = *src;
		dest++;
 		src++;
	}
	*dest = '\0';
}
           

通過以上三個例子,簡單了解字元串相關函數的操作原理,注意都是要判斷'\0',如果沒有'\0',則位址一直往後加,就會通路到非法記憶體。

以上3個例子隻寫簡單邏輯,并沒有考慮安全性,嚴謹性,大家可以自己實作下  strlen   strcpy。

再考慮 如下:

char *p = "hello";
char a[10] = "hello";
printf("%s",p);
strcpy(p,"bye");
printf("%s",a);
strcpy(a,"bye");
           

哪些代碼有問題?