简体   繁体   English

为char数组动态分配内存

[英]dynamic allocating memory for char array

having some understanding issues with the next block of code. 对下一部分代码有一些了解。

#include<iostream>
using namespace std;
int main() {
    char *str = "hi";
    char *p = new char[strlen(str) + 1];
    for (int i = 0; *(str + i); i++)
        *(p + i) = *(str + i);
    cout << p << endl;
    return 0;
}

Here's the result: 结果如下:

hi═¤¤¤¤

When i'm using debugger, i can see that my p points to an array of like 10 or 15 or some other amount of symbols (depends on compilation), so i'm getting extra symbols after "hi". 当我使用调试器时,我可以看到我的p指向一个由10或15或其他符号数量组成的数组(取决于编译),因此在“ hi”之后得到了更多的符号。 BUT, when i'm using strcpy(): 但是,当我使用strcpy()时:

#include<iostream>
using namespace std;
int main() {
    char *str = "hi";
    char *p = new char[strlen(str) + 1];
    strcpy(p, str);
    cout << p << endl;
    return 0;
}

i'm getting the result: 我得到结果:

hi

So, can someone, please, explain to me, why am i getting such a result with the first example of a program and how to rework it to get the result like in the second example. 因此,有人可以向我解释一下,为什么我在程序的第一个示例中得到了这样的结果,以及如何像在第二个示例中那样对它进行重新处理以得到结果。 Thanks in advance. 提前致谢。

You are not adding the terminating null character to p . 您没有在p添加终止空字符。

Add the line 添加行

*(p + i) = '\0';

after the for loop. for循环之后。 However, to do that, you have to declare i before the for loop. 但是,要这样做,您必须在for循环之前声明i

int i = 0;
for (i = 0; *(str + i); i++)
    *(p + i) = *(str + i);
*(p + i) = '\0';
cout << p << endl;

You forgot to terminate the string in your first exaple with a zero: 您忘记在第一个示例中以零终止字符串:

#include <cstddef>
#include <iostream>

int main()
{
    char const *str = "hi";
    std::size_t length = std::strlen(str);
    char *p = new char[length + 1];
    for (std::size_t i = 0; i < length; ++i)
        p[i] = str[i];
    str[length] = '\0';
    std::cout << p << '\n';
    delete[] p;
}

Please mind: String literals are immutable so they should be pointed to by char const* s. 请注意:字符串文字是不可变的,因此应由char const* s指向。 The correct type to hold sizes of objects in memory or indexes into them is std::size_t , not int . 可以在内存中保存对象大小或在其中建立索引的正确类型是std::size_t ,而不是int If you do manual memory management you have to make sure that you free the allocated memory by passing pointers obtained using new to delete and pointers from new[] to delete[] . 如果你这样做手动内存管理你必须确保你释放被传递使用指针获得分配的内存newdelete和指针的new[]delete[]

You shouldn't do memory management manually though. 但是,您不应该手动进行内存管理。 Use containers like std::string or std::vector or at least smart pointers like std::shared_ptr<> or std::unique_ptr<> . 使用容器,例如std::stringstd::vector或至少智能指针,例如std::shared_ptr<>std::unique_ptr<>

The answer is in the stopping condition of the loop, ie *(str + i) : 答案是在循环的停止条件下,即*(str + i)

for (int i = 0 ; *(str + i) ; i++)
    *(p + i) = *(str + i);

Note that there is no comparison operator in the expression. 请注意,表达式中没有比较运算符。 When an expression like this is used in a context where a logical condition is required, there is an implicit comparison to zero, ie *(str + i) means the same thing as *(str + i) != 0 . 在需要逻辑条件的上下文中使用这样的表达式时,存在与零的隐式比较,即*(str + i)含义与*(str + i) != 0

Now it should be clear why the string remains unterminated: loop stops when it discovers null terminator, and does not copy it into the destination string. 现在应该清楚为什么字符串保持未终止:循环在发现空终止符时停止,并且不将其复制到目标字符串中。

A slightly more "cryptic" way of doing the same thing would be coupling the comparison with the assignment, the way K&R book did: 一种更“神秘”的方法是将比较与赋值结合起来,就像K&R的书那样:

for (int i = 0 ; *(p + i) = *(str + i) ; i++)
    ;

Now the null test happens after the assignment, ensuring that the destination is null-terminated. 现在,在分配后进行空测试,以确保目的地为空终止。

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

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