1. 程式人生 > >【C基礎】空字元'\0'與字串

【C基礎】空字元'\0'與字串

空字元'\0'

空字元即NUL位元組,是一個ASCII值為0的控制字元,在程式程式碼中通常以轉義序列'\0'表示,在C語言中,空字元非常重要,主要體現在字串中。

字串

字串就是一串零個或多個字元,並且以位模式為全0的NUL位元組即空字元('\0')結尾。C語言中字串沒有顯示的資料型別,字串通常儲存在字元陣列或動態分配的記憶體中,在編碼操作中通常將整個字串作為操作物件,常用操作包括複製、查詢、比較等。

空字元與字串

1、空字元是字串的終止符。注:空字元本身不是字串的一部分,所以字串的長度並不包含空字元;

2、操作字串時,必須保證字串以空字元結尾(注:不以空字元結尾的字元序列,不是字串)。

如果在一個需要字串的地方(例如strlen函式的引數)使用了一個不是以空字元結尾的字元序列,會造成什麼結果呢?

a、strlen函式將無法知道空字元是沒有的,所以它將繼續進行查詢,一個接一個字元查詢直到發現一個空字元為止,或許它找幾百個字元才找到,而此時strlen函式的這個返回值從本質上說是一個隨機數或者說並沒有實際意義;

b、如果字串操作函式試圖訪問了系統分配給這個程式以外的記憶體範圍,程式會崩潰(通常表現為段溢位,程式異常退出)。

潛在不以空字元結尾的字元序列操作總結:

a、char *strcpy(char *dst, char const *src) 假如源字串src比目標字元陣列dst長,多餘的字元仍將被複制,它們將覆蓋原先儲存於目標字元陣列dst後面的記憶體空間的值(程式存在崩潰可能也會影響其他儲存值),最後目標字元陣列dst固然是不以空字元結尾的字元序列,所以必須保證目標字元陣列dst的空間能足以容納源字串src;

b、char *strncpy(char *dst, chat const *src, size_t len)  同上,首先必須保證目標字元陣列dst的空間能足以容納len個字元,除此之外,如果strlen(src)的值大於或等於len,那麼只有len個字元被複制到dst中,但dst最終將不會以空字元結尾;

c、char *strcat(char *dst, char const *src)  假如源字串src比目標字元陣列dst剩餘的空間長,多餘的字元仍將被複制,它們將覆蓋原先儲存於目標字元陣列dst後面的記憶體空間的值(程式存在崩潰可能也會影響其他儲存值),最後目標字元陣列dst固然是不以空字元結尾的字元序列,所以必須保證目標字元陣列dst剩餘的空間能足以容納源字串src;

d、char *strncat(char *dst, char const *src, size_t len) 同上,首先必須保證目標字元陣列dst剩餘的空間足以容納len個字元,除此之外,如果strlen(src)的值大於或等於len,那麼會有len個字元被複制到dst結尾處,但假如dst原有剩餘空間剛好可以容納len個字元,dst最終將不會以空字元結尾;

e、int strcmp(char const *s1, char const *s2)  strcmp函式的引數必須都以一個空字元結尾,如果並非如此,strcmp就可能對引數後面的位元組進行比較,這個比較結果將不會有實際意義,同理strncmp也一樣。

測試程式碼:

#include <stdio.h>
#include <string.h>

int main()
{
	int len;
	char str[5];
	
	strcpy(str, "12345678");                   /*字串拷貝*/
	len =strlen(str);                          /*字串長度*/
	printf("str_len:%d\n", strlen(str));       /*列印目標字串長度*/
	printf("str:%s\n", str);                   /*列印目標字串*/  
	
	return 0;
}
測試結果:


測試分析:

測試程式碼中,函式strcpy將大於目標字元陣列str儲存空間長度的字串拷貝給str(實際操作中會對其他儲存值進行覆蓋,危險操作,在作者的測試環境中未引發程式崩潰不代表在實際的開發環境中不會引起程式崩潰),目標字串str最多儲存5個字元,字元列印時結果為str:12345也證明如此,但字串長度卻實際輸出為6,長度6根本沒有實際意義,在其他測試環境中可能為大於5的任意值(如7、8等)。