带数组和指针的C字符串函数(strcopy、strcat…、strstrstr)

带数组和指针的C字符串函数(strcopy、strcat…、strstrstr),c,arrays,string,pointers,C,Arrays,String,Pointers,每当我在dev-C++中使用其中一个函数时(我知道它很旧,但出于某种原因,我的大学仍然在教它) 这些函数的第一个参数始终必须是数组(即: 但它不能是指向字符串bc的指针,因为某种原因,这会导致崩溃。 事实上,以这两种代码为例: 代码1: #include<stdio.h> #include<string.h> main() {char ch[20]="Hello world!"; char *ch2="Hello Galaxy!"; strcat(ch,ch2);

每当我在dev-C++中使用其中一个函数时(我知道它很旧,但出于某种原因,我的大学仍然在教它)

这些函数的第一个参数始终必须是数组(即:

但它不能是指向字符串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.
}
这对于几乎所有接受两个参数的字符串函数都是一样的。 这个问题的原因是什么。

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

使用
char ch[20]=“Hello World!”
时,您使用字符串文本的内容初始化数组,因此您将在
ch
中得到自己的字符串可修改副本

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

使用
char*ch2=“Hello Galaxy!”
您正在获取一个指向字符串文本的指针。您不应该试图修改字符串文本,因为这会调用未定义的行为(在您的情况下,这表现为崩溃)

 char ch[20] = "Hello world!"
使用
char ch[20]=“Hello World!”
时,您使用字符串文本的内容初始化数组,因此您将在
ch
中得到自己的字符串可修改副本

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

 char ch[20] = "Hello world!"
ch
是由字符串文本元素初始化的
char
数组(数组的其余部分用
0
初始化)

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

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

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

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


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

这与指针数组的大小有关。.溢出问题。。
char*ch2=“Hello Galaxy!”;
当您自动使用此选项时,*ch2的大小为14,带有空字符,但当您移动
ch[]
数组放入
*ch2
,您会收到一个错误。您无法将一个大小为20的数组移动到另一个大小为14的数组中…

这大约是指针数组的大小。溢出问题。。
char*ch2=“Hello Galaxy!”;
当您自动使用此选项时,*ch2的大小为14,带有空字符,但当您移动
ch[]
将数组放入
*ch2
,您会遇到一个错误。无法将一个大小为20的数组移动到另一个大小为14的数组中…

存在两个问题。第一个问题是字符串文字长度不足以容纳连接的字符串
“Hello world!Hello Galaxy!”
。分配的空间只有13个字节(12个字符加上用于终止字符串的“0”字节的空格)。连接的字符串需要26个字节(25个字符+1个空值字符)

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

  • 堆栈,在其中分配函数中声明的变量
  • 堆,其中对malloc/calloc/realloc的调用分配内存
  • 全局静态存储,其中分配非常量全局变量(在函数外部声明的变量)
  • 全局常量存储,其中分配所有声明的字符串文本和其他全局变量
    const
  • 原则上,前三个区域是可修改的。第四个区域不是,通常存储在操作系统标记为只读的内存中。当您将字符串literal
    “Hello Galaxy!”分配给
    char*ch2
    ,变量
    ch2`指向全局常量存储

    为了让您更好地了解,以下代码在我运行它时会显示一个segfault:

    #include <stdio.h>
    
    int main(int argc, char** argv)
    {
      char* s = "Foo bar baz";
      s[0] = 'B';
      printf("%s\n",s);
      return 0;
    }
    
    #包括
    int main(int argc,字符**argv)
    {
    char*s=“Foo-bar-baz”;
    s[0]=“B”;
    printf(“%s\n”,s);
    返回0;
    }
    

    segfault出现在
    s[0]=…
    行中,因为我正在访问操作系统标记为只读的存储。

    存在两个问题。第一个问题是字符串文字长度不足以容纳连接的字符串
    “Hello world!Hello Galaxy!”
    。分配的空间只有13个字节(12个字符加上用于终止字符串的“0”字节的空格)。连接的字符串需要26个字节(25个字符+1个空值字符)

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

  • 堆栈,在其中分配函数中声明的变量
  • 堆,其中对malloc/calloc/realloc的调用分配内存
  • 全局静态存储,其中分配非常量全局变量(在函数外部声明的变量)
  • 全局常量存储,其中分配所有声明的字符串文本和其他全局变量
    const
  • 原则上,前三个区域是可修改的。第四个区域不是,并且通常存储在操作系统标记为只读的内存中。当您指定字符串literal
    “Hel
    
    file.exe has stopped working Error.
    
     char ch[20] = "Hello world!"
    
     char *ch2="Hello Galaxy!";
    
    #include <stdio.h>
    
    int main(int argc, char** argv)
    {
      char* s = "Foo bar baz";
      s[0] = 'B';
      printf("%s\n",s);
      return 0;
    }
    
    char* str="Hello";
    
    char str2[]="Hello";
    
    size <executable-file-neme>
    
    objdump -D  <executable-file-neme>