带有数组和指针的C字符串函数(strcpy,strcat ...,strstr)

时间:2012-07-26 22:36:59

标签: c arrays string 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!)

但反码2崩溃了。

码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.

对于几乎所有带有两个参数的字符串函数,这都是相同的。 造成这个问题的原因是什么。

6 个答案:

答案 0 :(得分:9)

使用char *ch2 = "Hello Galaxy!";,您将获得指向字符串文字的指针。您永远不应该尝试修改字符串文字,因为这会调用未定义的行为(在您的情况下表现为崩溃)。

使用char ch[20] = "Hello World!";,您正在使用字符串文字的内容初始化数组,因此您最终会在ch中使用您自己的可修改字符串副本。

另外,请注意,Hello World!Hello Galaxy!不足以容纳20个字符,这也是未定义的行为,称为溢出缓冲区。

答案 1 :(得分:2)

 char ch[20] = "Hello world!"

ch是一个由字符串文字元素初始化的char数组(数组的其余部分用0初始化)。

 char *ch2="Hello Galaxy!";

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

字符串文字不需要在C中修改。修改字符串文字是C中未定义的行为。

答案 2 :(得分:1)

有两个问题。第一个是你的字符串文字不足以保存连接字符串"Hello world!Hello Galaxy!"。分配的空间仅为13个字节(12个字符加上用于终止字符串的'0'字节的空间)。连接的字符串需要26个字节(25个字符+ 1个空值char)。

然而,这不是真正的问题。真正的问题是你正在访问你不应该访问的内存,并且操作系统经常会保护它。 C的大多数实现提供了四个存储区域:

  1. 堆栈,您在函数中声明的变量已分配
  2. 堆,其中对malloc / calloc / realloc的调用分配内存
  3. 全局静态存储,其中分配了非const全局变量(在函数外部声明的变量)。
  4. 全局常量存储,其中分配了所有字符串文字和其他声明为const的全局变量。
  5. 前三个领域原则上是可修改的。第四个区域不是,并且通常存储在操作系统标记为只读的内存中。将字符串文字"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;
    }
    

    段错误发生在s[0] = ...行,因为我正在访问操作系统标记为只读的存储。

答案 3 :(得分:0)

那是关于指针数组的大小..溢出问题.. char *ch2="Hello Galaxy!";当你自动使用它时,* ch2的大小在空字符处获得14但是当你将ch[]数组移动到*ch2时,会出现错误。你不能将具有20个大小的数组移动到另一个具有14个大小的数组......

答案 4 :(得分:0)

字符串文字是只读的。这意味着如果你指定:

char* str="Hello";

你不能将str作为strcpy和strcat的第一个参数传递,因为这会导致写入只读内存。 如果你用这种方式声明它:

char str2[]="Hello";

然后str2数组存储在堆栈中,您可以更改它的值 你仍然可以将str传递给strcmp之类的函数(只读取wto字符串并比较它们),或者作为strcat和strcpy的第二个参数,因为这不会导致字符串被写入。

答案 5 :(得分:0)

您收到错误,因为您尝试访问进程的代码部分是只读的。 这是您在代码中出现的字符串文字,以及您在赋值给指针变量时使用的字符串文字的地址。 所以你可以访问代码但不能修改它。

每个可执行文件都包含一些部分 像...

1.text(您的程序代码以及此处提供的字符串文字)

2.data未初始化

3.data初始化

你可以通过命令

来解决这个问题
size <executable-file-neme>

还使用命令

objdump -D  <executable-file-neme>