繁体   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