C sprintf数组字符指针
谁能告诉我我做错了什么?为什么我的程序会出错? 我正在尝试在C sprintf数组字符指针,c,arrays,pointers,C,Arrays,Pointers,谁能告诉我我做错了什么?为什么我的程序会出错? 我正在尝试在string1和string2之间插入第三个字符串 #include <stdio.h> int main (void) { char *string1 = "HELLO"; char *string2 = "WORLD"; char *stringX = "++++"; char *string3; printf ("%s,%s\n",string1,string2); sprintf(string3,"%s%s%s
string1
和string2
之间插入第三个字符串
#include <stdio.h>
int main (void)
{
char *string1 = "HELLO";
char *string2 = "WORLD";
char *stringX = "++++";
char *string3;
printf ("%s,%s\n",string1,string2);
sprintf(string3,"%s%s%s",string1,stringX,string2);
printf ("NewVar: %s",string3);
}
如果需要将
string3
放在堆上,则需要使用malloc
为其分配空间,如果不需要,则需要将其声明为字符数组。sprintf
不会为其写入的字符串分配内存。您必须提供一个有效字符串供其写入,但当前正在向其传递一个未初始化的指针
最简单的解决办法是改变
char *string3;
sprintf(string3,"%s%s%s",string1,stringX,string2);
到
在这种情况下,您可能希望使用snprintf
来防止缓冲区溢出
char string3[200];
snprintf(string3,sizeof(string3),"%s%s%s",string1,stringX,string2);
或者,您也可以通过在运行时确定string3
的大小来处理较长的源字符串,并在使用完后注意释放该内存
char* string3 = malloc(strlen(string1) + strlen(stringX) + strlen(string2) + 1);
if (string3 == NULL) {
// handle out of memory
}
sprintf(string3,"%s%s%s",string1,stringX,string2);
...
free(string3);
sprintf
将值存储在那里。问题是指针string3有未初始化的值,所以您只是在覆盖随机内存
您可以选择使用静态字符串缓冲区:
char string3[20];
snprintf(string3, sizeof(string3), "Hello!");
或者,您可以在基于GNU libc的系统上使用asprintf
,自动分配适当的空间:
char * string3;
asprintf(&string3, "Hello!");
// ... after use
free(string3); // free the allocated memory
想象一下,你有一堆现金要放在公文包里。你需要什么?你必须测量现金的大小才能知道公文包有多大,你需要一个把手来方便地携带现金
现金是你的条件。公文包是内存空间。公文包手柄是指针
衡量你的现金:strlen(string1)+strlen(string2)+strlen(stringX)
。
称之为“总计”
现在准备一个足够大的公文包:malloc(总计+1)
并在其上放置一个句柄:string3
把这些拼凑起来
char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);
那么,第一次尝试有什么问题?你没有公文包。你有现金,你有把手,中间没有公文包。它似乎以一种随机的方式工作,因为编译器给了你一个脏垃圾箱来存放现金。垃圾箱有时有空间,有时没有。如果没有,我们称之为“分段错误”
只要有数据,就必须为该数据分配空间。编译器为常量字符串分配空间,如“HELLO”
。但是您必须为运行时生成的字符串分配空间。假设您将i
定义为inti
;在此级别中,您告诉我将存储整数
,但I
变量中仍然没有有意义的数字。
当您定义char*string3
时,您会告诉string3
将存储char指针,但仍然没有有意义的地址。所以您必须为这个变量分配内存
string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
作为提示:数据应该写在哪里?你认为指针指向哪里?@glglglgl-我以为string3没有指向任何东西,但当我打印f(“%p”,string3)时,它似乎指向一个内存位置。但指向一个未指定的位置…@user2953313:你在说什么内存地址<代码>字符串3
未指向任何有意义的内存地址。它的值是不确定的,从技术上讲根本不是内存地址。它可能“看起来”指向“内存位置”,但实际上这只是一种幻觉——是未定义行为的结果。string3
不指向任何可写内存。char*
的大小在这里不相关-sprintf
将尝试写入string3
指向的位置,它不会尝试写入指针本身。是的,我尝试通过类比来解释它失败了。会更正的。大家好,谢谢你们的解释。当我打印带有%p的string3时,为什么它指向内存位置?当它不应该指向内存位置时,根据上面的注释。我编辑了我的代码来突出显示它。@user2953313 C不会将变量初始化为任何特定值。指向的地址不能保证,但很可能是以前写入该堆栈位置的地址。尝试取消引用未初始化的指针会导致未定义的行为。有时它会崩溃;其他情况下,它可能会起作用。@user2953313若要获得初始化,请使用calloc()而不是malloc。在我的类比中,这是旧公文包和脏公文包(malloc)或新公文包和干净公文包(calloc)之间的区别。我从calloc开始,然后如果性能是一个问题,而清洁度不是,我会切换到malloc.,感谢使用malloc给出的答案。空字符是+1吗?@user2953313很高兴它有帮助。是的,+1表示nul终端。我们的asprintf示例不正确-string3应该是char*而不是char。也许还需要补充一点,asprintf不是一个标准的C函数(或者我认为甚至不是Posix)。@NigelHarper:谢谢,修正了。asprintf是GNU的一个扩展,在well。
char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);
string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);