简体   繁体   English

C sprintf 数组字符指针

[英]C sprintf array char pointers

Could anyone tell me what am i doing wrong over here?谁能告诉我我在这里做错了什么? Why does my program segfault ?为什么我的程序段错误? I am trying to insert a third string between string1 and string2 .我试图在string1string2之间插入第三个字符串。

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

Why doesn't sprintf store the resultant value at the memory address pointed by string3 ?为什么sprintf不将结果值存储在string3指向的内存地址处? It works when i declare string3 as an ordinary array but not when its a pointer to char array.当我将string3声明为普通数组时它起作用,但当它是指向char数组的指针时不起作用。

I thought string3 wasnt pointing to any memory location, but it does seem to when i do printf("%p",string3);我认为string3指向任何内存位置,但是当我执行printf("%p",string3);时似乎确实如此printf("%p",string3);

Output:输出:

# ./concat
HELLO,WORLD,0x40042

Imagine you have a pile of cash that you want to put in a briefcase.想象一下,您有一堆现金要放在公文包中。 What do you need?你需要什么? You have to measure the size of the cash to know how big a briefcase to use, and you need a handle to conveniently carry the cash around.您必须测量现金的大小才能知道使用多大的公文包,并且您需要一个把手来方便地携带现金。

The cash is your strings.现金是你的字符串。 The briefcase is memory space.公文包是内存空间。 The briefcase handle is the pointer.公文包句柄是指针。

  1. Measure your cash: strlen(string1) + strlen(string2) + strlen(stringX) .衡量您的现金: strlen(string1) + strlen(string2) + strlen(stringX) Call this "total".称其为“总计”。
  2. Now get a big enough briefcase: malloc(total+1)现在得到一个足够大的公文包: malloc(total+1)
  3. And put a handle on it: string3并在其上放一个句柄: string3

Cobbling all that together...将所有这些拼凑在一起......

char *string3 = malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);
sprintf(string3, "%s%s%s", string1, stringX, string2);

So what was wrong with the first attempt?那么第一次尝试有什么问题呢? You had no briefcase.你没有公文包。 You have cash, and you have a handle, but no briefcase in the middle.你有现金,你有一个把手,但中间没有公文包。 It appeared to work, in a random kind of way, because the compiler gave you a dirty dumpster to hold the cash.它似乎以一种随机的方式工作,因为编译器给了你一个肮脏的垃圾箱来存放现金。 Sometimes the dumpster has room, sometimes it doesn't.有时垃圾箱有空间,有时没有。 When it doesn't, we call that "segmentation fault".如果没有,我们称之为“分段错误”。

Whenever you have data, you have to allocate space for that data.只要有数据,就必须为该数据分配空间。 The compiler allocates space for your constant strings, like "HELLO" .编译器为常量字符串分配空间,例如"HELLO" But you have to allocate space for strings built at run-time.但是您必须为运行时构建的字符串分配空间。

sprintf does store the value there. sprintf确实将值存储在那里。 The problem is that the pointer string3 has uninitialized value, so you're just overwriting random memory.问题是指针 string3 具有未初始化的值,因此您只是覆盖随机内存。

One option you have is to use static string buffer:您拥有的一种选择是使用静态字符串缓冲区:

char string3[20];
snprintf(string3, sizeof(string3), "Hello!");

Or, you can use asprintf on GNU libc-based systems to allocate proper space automatically:或者,您可以在基于 GNU libc 的系统上使用asprintf自动分配适当的空间:

char * string3;
asprintf(&string3, "Hello!");
// ... after use
free(string3); // free the allocated memory

sprintf does not allocate memory for the string it writes. sprintf不会为其写入的字符串分配内存。 You have to provide a valid string for it to write into but are currently passing it an uninitialised pointer.您必须提供一个有效的字符串才能写入,但当前正在向它传递一个未初始化的指针。

The easiest fix is to change最简单的解决方法是改变

char *string3;
sprintf(string3,"%s%s%s",string1,stringX,string2);

to

char string3[200];
sprintf(string3,"%s%s%s",string1,stringX,string2);

You may want to guard against buffer overflows in this case by using snprintf instead在这种情况下,您可能希望通过使用snprintf来防止缓冲区溢出

char string3[200];
snprintf(string3,sizeof(string3),"%s%s%s",string1,stringX,string2);

Alternatively, you could also cope with larger lengths of source string by determining the size of string3 at runtime, taking care to free this memory when you have finished with it.或者,您还可以通过在运行时确定string3的大小来处理更大长度的源字符串,并在完成后注意free此内存。

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

如果需要将string3放在堆上,则需要使用mallocstring3分配空间,如果不需要,则将其声明为字符数组。

suppose you define i as int i ;假设您将i定义为int i in this level you tell that I will store integer number but still there is not a meaningful number in i variable.在这个级别中,您告诉我将存储integer numberi变量中仍然没有有意义的数字。 like this when you define char *string3 you tell that string3 will store char pointer but still there is not meaningful address.像这样,当您定义char *string3您告诉string3将存储字符指针,但仍然没有有意义的地址。 so you must allocate memory to this variable所以你必须为这个变量分配内存

string3 =  malloc(strlen(string1)+strlen(stringX)+strlen(string2)+1);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM