Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C sprintf数组字符指针_C_Arrays_Pointers - Fatal编程技术网

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);