#include<string.h>
#include<stdio.h>
void main()
{
char *str1="hello";
char *str2="world";
strcat(str2,str1);
printf("%s",str2);
}
如果我运行此程序,我将运行程序终止。
请帮帮我。
如果我使用它:
char str1[]="hello";
char str2[]="world";
然后它正在运作!
但为什么
char *str1="hello";
char *str2="world";
此代码无效????
答案 0 :(得分:5)
你正在学习一本坏书。主函数应声明为
int main (void);
将其声明为void会在应用程序完成时调用未定义的行为。好吧,它还没有完成,但最终会完成。
获取一本关于C语言的书。你会发现
char *srt1="hello";
编译就像编写
一样static const char secret_array [6] = { 'h', 'e', 'l', 'l', 'o', 0 };
char* srt1 = (char*) &secret_array [0];
而
char srt1[]="hello";
编译就像编写
一样char srt1 [6] = { 'h', 'e', 'l', 'l', 'o', 0 };
两个strcat调用都是严重的错误,因为strcat调用的目标没有足够的内存来包含结果。第一次调用也是一个bug,因为你试图修改常量内存。在第一种情况下,这个bug会导致崩溃,这对你来说是一件好事并且很幸运。在第二种情况下,不会立即检测到错误。哪个运气不好。您可以打赌,如果您在运送给客户的程序中使用这样的代码,如果您运气不好会导致错误,并导致错误的结果,这将导致您的客户花费大量金钱并以其他方式起诉。
答案 1 :(得分:2)
在您的代码中。
char *srt1="hello";
你创建了一个指针并将其指向一个常量字符串。编译器将其放在标记为只读的内存中。
因此strcat
将尝试修改导致未定义行为的内容。
它没有名称,并且具有静态存储持续时间(意味着它在程序的整个生命周期中存在);和一个名为p的指针类型的变量,它被初始化为该未命名的只读数组中第一个字符的位置。
请参阅my answer以正确理解为什么它首先工作而不是第二种情况。
答案 2 :(得分:1)
字符串文字是只读的,您无法更改它们。
此:
char *srt2="world";
表示srt2
(错误名称,btw)是指针变量,指向包含常量数据"world"
(以及终止'\0'
字符)的内存。六个字符后没有额外的空间,你甚至无法更改字母。
你需要:
char str2[32] = "world";
另一方面,这使str2
成为一个包含32个字符的数组,其中前6个字符初始化为"world"
,终止'\0'
。可以附加到此,因为新字符可以适合现有数组,只要您不超越并尝试存储超过32个字符(包括终结符)。
答案 3 :(得分:0)
char *srt1="hello";
char *srt2="world";
当你声明这样的字符串时,它存储在只读存储器中!
您无法更改存储在只读内存中的变量!
执行strcat
时,它会尝试修改只读内存中的字符串。所以这里不允许!它是“未定义的”。
答案 4 :(得分:0)
在你的程序中,不应该写入str1和str2,因为它们被声明为只读内存的指针。要看到这个,请执行'objdump -s a.out',您将看到以下内容:
Contents of section .rodata:
400640 01000200 68656c6c 6f00776f 726c6400 ....hello.world.
400650 257300 %s.
strcat尝试写入内存的那一部分,从而导致分段错误。
答案 5 :(得分:0)
您也可以使用数组。这是我的一个简单的程序,我遇到了这样的问题,但在这个问题中你必须声明数组的大小。喜欢,
mahe = [10]
。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char cname[10] = "mahe";
strcat(cname, "Karim");
printf("%s\n", cname);
return 0;
}