簡體   English   中英

帶有數組和指針的C字符串函數(strcopy,strcat…,strstr)

[英]C string function (strcopy,strcat…,strstr) with arrays and pointers

每當我在dev-C ++中使用這些功能之一時(我知道它的悠久歷史,但由於某種原因仍在我的大學任教。)

strcat,strcpy,strcmp,strchr...//And their variants stricmp...

這些函數的第一個參數始終必須是一個數組(即:

char ch[]="hello";

但是由於某種原因,它不能是指向字符串bc的指針,這會導致崩潰。 實際上,請看下面兩個代碼:

代碼1:

#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
 char *ch2="Hello Galaxy!";
 strcat(ch,ch2);
 printf("%s",ch);
 scanf("%d")//Just to see the output.
}

該代碼可以正常工作並給出預期的結果(Hello World!Hello Galaxy!)

但是反向code2崩潰了。

代碼2:

#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
 char *ch2="Hello Galaxy!";
 strcat(ch2,ch);
 printf("%s",ch2);
 scanf("%d")//Just to see the output.
}

此代碼崩潰並導致

file.exe has stopped working Error.

幾乎所有帶有兩個參數的字符串函數都是相同的。 是什么原因導致此問題。

使用char *ch2 = "Hello Galaxy!"; 您將獲得一個指向字符串文字的指針。 您永遠不要嘗試修改字符串文字,因為這會引起未定義的行為(在您的情況下已表現為崩潰)。

使用char ch[20] = "Hello World!"; 您正在使用字符串文字的內容初始化數組,因此最終在ch獲得了自己的字符串可修改副本。

另外,請注意,對於Hello World!Hello Galaxy! ,20個字符是不夠的Hello World!Hello Galaxy! 以適應,這也是未定義的行為,稱為緩沖區溢出。

 char ch[20] = "Hello world!"

ch是由字符串文字的元素初始化的char數組(該數組的其余部分初始化為0 )。

 char *ch2="Hello Galaxy!";

ch2是指向字符串文字的指針。

不需要在C中修改字符串文字。在C中,修改字符串文字是未定義的行為。

有兩個問題。 首先是您的字符串文字長度不足以容納連接的字符串"Hello world!Hello Galaxy!" 分配的空間只有13個字節(12個字符加上終止字符串的'0'字節的空間)。 串聯的字符串需要26個字節(25個字符+ 1個空值字符)。

但是,這不是真正的問題。 真正的問題是您正在訪問不應訪問的內存,並且操作系統經常會保護它。 C的大多數實現都提供四個存儲區域:

  1. 堆棧,您在函數中聲明的變量將分配到該堆棧中
  2. 堆,在其中調用malloc / calloc / realloc分配內存
  3. 全局靜態存儲,其中分配了非常量全局變量(在函數外部聲明的變量)。
  4. 全局常量存儲,其中分配了所有字符串文字和其他聲明為const全局變量。

原則上,前三個區域是可修改的。 第四區域不是,通常存儲在操作系統標記為只讀的內存中。 當您分配字符串文字"Hello Galaxy!" to "Hello Galaxy!" to char * ch2 , the variable ch2`指向全局常量存儲。

為了給您一個更好的主意,當我運行它時,以下代碼一般將出現段錯誤:

#include <stdio.h>

int main(int argc, char** argv)
{
  char* s = "Foo bar baz";
  s[0] = 'B';
  printf("%s\n",s);
  return 0;
}

segfault發生在s[0] = ...行中,因為我正在訪問操作系統已將其標記為只讀的存儲。

那就是指針數組的大小。溢出問題。char char *ch2="Hello Galaxy!"; 當您自動使用此參數時,* ch2的大小將為14,帶有空字符,但是當您將ch[]數組移至*ch2 ,會出現錯誤。 您不能將大小為20的數組移動到大小為14的另一個數組中...

字符串文字是只讀的,這意味着如果您分配:

char* str="Hello";

您不能將str作為strcpy和strcat的第一個參數傳遞,因為這將導致覆蓋只讀內存。 相反,如果您這樣聲明:

char str2[]="Hello";

然后將str2數組存儲在堆棧中,然后可以更改其值。
您仍然可以將str傳遞給諸如strcmp(僅讀取wto字符串並進行比較)之類的函數,或者作為strcat和strcpy的第二個參數傳遞,因為這不會導致字符串被寫入。

您收到錯誤消息是因為您嘗試訪問進程的代碼部分,該部分是只讀的。 那是您的字符串文字出現在代碼中,以及您在分配給指針變量時使用的字符串文字的地址。 因此,您可以訪問代碼,但不能修改它。

每個可執行文件都包含某些部分,例如...

1.text(程序代碼以及此處的字符串文字)

2.數據未初始化

3.數據初始化

您可以通過命令非常

size <executable-file-neme>

也使用命令

objdump -D  <executable-file-neme>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM