使用NULL作为数组中的终结符?

时间:2010-12-02 18:24:23

标签: c++ arrays string null containers

我喜欢“重新发明轮子”用于学习目的,所以我正在为字符串工作一个容器类。将NULL字符用作数组终止符(即数组中的最后一个值是NULL)是否会导致对以null结尾的字符串的干扰?

我认为如果添加一个空字符串只会是一个问题,但我可能会遗漏一些东西。

编辑:这是用C ++编写的。

7 个答案:

答案 0 :(得分:2)

""是C和C ++中的空字符串,而不是NULL。请注意,""只有一个元素(而不是零),这意味着它等同于{'\0'}作为char的数组。

char const *notastring = NULL;
char const *emptystring = "";

emptystring[0] == '\0';  // true
notastring[0] == '\0';   // crashes

答案 1 :(得分:2)

不,它不会,因为你不会存储在char数组中,你将存储在char *数组中。

char const* strings[] = {
  "WTF"
, "Am"
, "I"
, "Using"
, "Char"
, "Arrays?!"
, 0
};

答案 2 :(得分:2)

这取决于您要存储的字符串类型。

如果你要存储C风格的字符串,它们基本上只是指向字符数组(char*)的指针,那么NULL指针值和空字符串之间就有区别。前者表示指针为“空”,后者表示指针指向包含字符值为0('\0')的单个项的数组。所以指针仍然有一个值,测试它(if (foo[3]))将按预期工作。

如果您要存储的是string类型的C ++标准库字符串,则没有NULL值。那是因为没有指针,string类型被视为单个值。 (虽然指针在技术上不是,但可以看作是参考。)

答案 3 :(得分:2)

我觉得你很困惑。虽然C字符串是“空终止”,但没有“NULL”字符。 NULL是null 指针的名称。 C字符串的终止符是空字符,即值为零的字节。在ASCII中,这个字节(有点令人困惑)命名为NUL

假设您的类包含用于存储字符串数据的char数组。你不需要“标记数组的结尾”;数组具有在编译时设置的特定大小。你需要知道实际使用了多少空间;字符串数据上的null-terminator为您完成 - 但您可以通过实际记住长度来获得更好的性能。另外,带有静态大小的char缓冲区的“string”类根本不是很有用,因为缓冲区大小是你可以拥有的字符串长度的上限。

因此,更好的字符串类将包含类型为char*的指针,该指针指向new[] s的动态分配(via char)数组。同样,“标记数组的结尾”是没有意义的,但是你要记住字符串的长度(即使用的空间量)和分配的大小(即空间的数量)可以在必须重新分配之前使用。

答案 4 :(得分:1)

当您从std::string进行复制时,请使用迭代器begin()end()并且您不必担心NULL - 实际上,只有当您使用NULL时才会出现NULL call c_str()(在这种情况下,指向的内存块将有一个NULL来终止字符串。)如果你想memcpy使用data()方法。

答案 5 :(得分:0)

为什么不遵循vector使用的模式 - 存储容器类中的元素数量,然后总是知道其中有多少个值:

vector<string> myVector;

size_t elements(myVector.size());

使用x实例化字符串,其中const char* x = 0;可能会有问题。在执行此操作时,在Visual C ++ STL中查看此代码:

_Myt& assign(const _Elem *_Ptr)
    {   // assign [_Ptr, <null>)
    _DEBUG_POINTER(_Ptr);
    return (assign(_Ptr, _Traits::length(_Ptr)));
    }

static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)
    {   // find length of null-terminated string
    return (_CSTD strlen(_First));
    }

答案 6 :(得分:0)

#include "Maxmp_crafts_fine_wheels.h"
MaxpmContaner maxpm;
maxpm.add("Hello");
maxpm.add(""); // uh oh, adding an empty string; should I worry?
maxpm.add(0);

此时,作为MaxpmContainer的用户,他没有阅读您的文档,我希望如下:

strcmp(maxpm[0],"Hello") == 0;
*maxpm[1] == 0;
maxpm[2] == 0;

通过“将其解释为存储器地址”运算符*,避免了位置2处的零终结器与位置1处的空字符串之间的干扰。位置一不会为零;它将是一个整数,如果将其解释为内存地址,则结果为零。位置2将为零,如果您将其解释为内存地址,则结果将是从程序中突然无序退出。