有没有一个函数(或多个函数)可以将一个字符串复制到内存中的新空间?

huangapple go评论105阅读模式
英文:

Is there a function(s) to copy a string into a new space in memory

问题

如果我想在C编程中将字符串`"Best School"`复制到内存中的新空间,我可以使用哪些语句来为它保留足够的空间?

我已经尝试过以下两种方式:

malloc(strlen("Best School") + 1)


以及

malloc(sizeof("Best School"))

英文:

If I want to copy the string "Best School" into a new space in memory in C programming, What statement(s) can I use to reserve enough space for it?

I have tried using this:

malloc(strlen("Best School") + 1)

And this also

malloc(sizeof("Best School"))

答案1

得分: 3

最简单和最安全的分配一块内存并将以null结尾的字符串复制到其中的方法是:

char *ptr = strdup("Best School");

strdup()<string.h>中声明,自从其创立以来一直是POSIX标准的一部分,并且最终在C23标准中成为了标准C的一部分。它在大多数系统上都可用,并且可以这样定义:

#include <stdlib.h>

char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    return p ? memcpy(p, s, size) : NULL;
}

或者,您可以直接使用mallocstrlenstrcpy

malloc分配给定大小的内存块。内存未初始化,其内容是不确定的,因此如果分配成功,您必须将字符串复制到其中,包括空终止符('\0')。"Best school"是一个以null结尾的字符串,有12个字节:11个字符加上一个null终止符字节。

// 为null终止符添加1
char *ptr = malloc(strlen("Best school") + 1);
if (ptr) strcpy(ptr, "Best school");

对于字符串字面量,甚至可以使用sizeof

// sizeof包括字符串字面量中的null终止符
char *ptr = malloc(sizeof "Best school");
if (ptr) strcpy(ptr, "Best school");

但上述两种解决方案都容易出错,因为:

  • 容易忘记为null终止符分配或复制额外的字节。这个错误会导致未定义的行为,但由于分配的粒度,可能在一段时间内不会被检测到:例如,为"Best school"分配11个字节可能返回一个16字节的块,第12个字节可能恰好是null字节,特别是如果此内存以前未被使用。这种未定义的行为是隐匿的,会在最糟糕的时候出现问题。
  • sizeof版本**仅适用于字符串字面量!**如果要分配指向的字符串的副本,sizeof(ptr)将评估为指针的大小,而不是字符串的大小,对于除最短字符串以外的所有字符串都会导致未定义的行为。这个解决方案适用于问题中的示例,但应该被忽略。

推荐的解决方案是使用strdup

英文:

The simplest and safest way to allocate a block of memory and copy a null terminated string into it is:

    char *ptr = strdup(&quot;Best School&quot;);

strdup() is declared in &lt;string.h&gt;, has been part of the POSIX Standard since its inception and finally made it into Standard C as of C23. It is available on most systems and can be defined this way:

#include &lt;stdlib.h&gt;

char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    return p ? memcpy(p, s, size) : NULL;
}

Alternately, you could use malloc, strlen and strcpy directly:

malloc allocates a block memory of a given size. The memory is uninitialized, its contents are indeterminate, so if the allocation was successful, you must then copy the string into it, including the null terminator (&#39;\0&#39;). &quot;Best school&quot; is a null terminated string with 12 bytes: 11 characters plus a null terminator byte.

    // add 1 for the null terminator
    char *ptr = malloc(strlen(&quot;Best school&quot;) + 1);
    if (ptr) strcpy(ptr, &quot;Best school&quot;);

And for string literals, you could even use sizeof:

    // sizeof includes the null terminator in a string literal
    char *ptr = malloc(sizeof &quot;Best school&quot;);
    if (ptr) strcpy(ptr, &quot;Best school&quot;);

But both of the above solutions are error prone because:

  • one can easily forget to allocate or copy the extra byte for the null terminator. This bug causes undefined behavior, but can go undetected for some time because of the allocation granularity: e.g. allocating 11 bytes for &quot;Best school&quot; may return a block of 16 bytes and the 12th byte may happen to be a null byte, especially if this memory has not been used before. This kind of undefined behavior is sly and will bite at the worst time.
  • the sizeof version only works for string literals! If you want to allocate a copy of a string you only have a pointer to, sizeof(ptr) will evaluate to the size of the pointer, not that of the string, leading to undefined behavior for all but the shortest strings. This solution works for the example in the question, but should be disregarded.

The recommended solution is strdup.

答案2

得分: 0

你需要分配内存并复制原始字符串。我建议一开始(出于教育目的)编写所有函数。以下是示例:

size_t mystrlen(const char *str)
{
    char *end = str;
    if(str) while(*end) end++;
    return end - str;
}

void *mymemcpy(void *dest, const void *src, size_t len)
{
    if(dest && src)
    {
        const unsigned char *ucsrc = src;
        unsigned char *ucdest = dest;
        while(len--) *ucdest++ = *ucsrc++;
    }
    return dest;
}

char *mystrdup(const char *str)
{
    char *newstr = NULL;
    size_t len = 0;
    if(str)
    {
        len = mystrlen(str) + 1;
        newstr = malloc(len);
        if(newstr)
        {
            mymemcpy(newstr, str, len);
        }
    }
    return newstr;
}
英文:

You need to allocate the memory and copy the original string. I would advice at the beginning (for educational purposes) to write all functions. Here is an example

size_t mystrlen(const char *str)
{
    char *end = str;
    if(str) while(*end) end++;
    return end - str;
}

void *mymemcpy(void *dest, const void *src, size_t len)
{
    if(dest &amp;&amp; src)
    {
        const unsigned char *ucsrc = src;
        unsigned char *ucdest = dest;
        while(len--) *ucdest++ = *ucsrc++;
    }
    return dest;
}

char *mystrdup(const char *str)
{
    char *newstr = NULL;
    size_t len = 0;
    if(str)
    {
        len = mystrlen(str) + 1;
        newstr = malloc(len);
        if(newstr)
        {
            mymmemcpy(newstr, str, len);
        }
    }
    return newstr;
}

huangapple
  • 本文由 发表于 2023年8月10日 16:50:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76874087.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定