1

每当我在 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.

这对于几乎所有带有两个参数的字符串函数都是一样的。这个问题的原因是什么。

4

6 回答 6

9

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

随着char ch[20] = "Hello World!";您使用字符串文字的内容初始化一个数组,因此您最终得到了您自己的可修改的字符串副本ch

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

于 2012-07-26T22:39:11.303 回答
2
 char ch[20] = "Hello world!"

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

 char *ch2="Hello Galaxy!";

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

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

于 2012-07-26T22:40:08.820 回答
1

有两个问题。首先是您的字符串文字不够长,无法容纳连接的字符串"Hello world!Hello Galaxy!"。分配的空间只有 13 个字节(12 个字符加上终止字符串的“0”字节的空间)。连接的字符串需要 26 个字节(25 个字符 + 1 个空值字符)。

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

  1. 堆栈,在其中分配您在函数中声明的变量
  2. 堆,调用 malloc/calloc/realloc 分配内存
  3. 全局静态存储,其中分配了非常量全局变量(在函数之外声明的变量)。
  4. const全局常量存储,其中分配了所有字符串文字和其他声明的全局变量。

前三个区域原则上是可以修改的。第四个区域不是,并且通常存储在操作系统标记为只读的内存中。当您将字符串文字"Hello Galaxy!" tochar* ch2 , the variablech2` 分配到全局常量存储中时。

为了给你一个更好的主意,下面的代码在我运行它时一般会出现段错误:

#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] = ...行中,因为我正在访问操作系统已标记为只读的存储。

于 2012-07-26T22:55:31.357 回答
0

这大约是指针数组的大小..溢出问题.. char *ch2="Hello Galaxy!";当您自动使用它时, *ch2 的大小为 14 并带有空字符,但是当您将ch[]数组移动到 时*ch2,您会收到错误消息。你不能将一个大小为 20 的数组移动到另一个大小为 14 的数组中......

于 2012-07-26T22:49:10.280 回答
0

字符串文字是只读的。这意味着如果您分配:

char* str="Hello";

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

char str2[]="Hello";

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

于 2012-07-27T01:02:03.467 回答
0

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

每个可执行文件都包含一些部分,例如...

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

2.数据未初始化

3.数据初始化

您可以通过命令对此进行验证

size <executable-file-neme>

也使用命令

objdump -D  <executable-file-neme>
于 2012-07-27T04:32:43.933 回答