c语言是否所有的字符串都有终止符,关于c ++:定义一个字符串,末尾不带空终止符char()...

在C / C ++中,有什么不同的方法来定义一个字符串,该字符串末尾没有null终止的char( 0)?

编辑:我只对字符数组感兴趣,而不对STL字符串感兴趣。

C / C ++ ?? [.....]

那不是C中的字符串。在C中,字符串定义为以NUL字符结尾的字符数组。 您要求的只是一个字符数组。

似乎很多人都在重复相同的答案:使用std :: string。

自C ++ 11起,std :: string终止为nul:en.cppreference.com/w/cpp/string/basic_string/data

通常如另一位海报写道:

char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};

或者如果您当前的C字符集是ASCII(通常为true)(今天的EBCDIC很少)

char s[6] = {115, 116, 114, 105, 110, 107};

还有一种很大程度上被忽略的方式仅适用于C(不适用于C ++)

char s[6] ="string";

如果数组大小太小而不能容纳最后一个0(但足够容纳常量字符串的所有其他字符),则不会复制最后一个零,但它仍然是有效的C(但无效的C ++)。

显然,您也可以在运行时执行此操作:

char s[6];

s[0] = 's';

s[1] = 't';

s[2] = 'r';

s[3] = 'i';

s[4] = 'n';

s[5] = 'g';

或(与上面的ASCII字符集相同的注释)

char s[6];

s[0] = 115;

s[1] = 116;

s[2] = 114;

s[3] = 105;

s[4] = 110;

s[5] = 103;

或使用memcopy(或memmove或bcopy,但在这种情况下没有好处)。

memcpy(c,"string", 6);

或strncpy

strncpy(c,"string", 6);

应该理解的是,在C中没有字符串这样的东西(在C ++中没有字符串对象,但这完全是另一回事了)。所谓的字符串只是char数组。甚至名称char都具有误导性,它不是char而是一种数字类型。我们本来可以称它为字节,但是在过去,使用9位寄存器或类似的东西存在奇怪的硬件,字节意味着8位。

由于char通常用于存储字符代码,因此C设计师想到了一种比在char中存储数字更简单的方法。您可以在简单的引号之间加上一个字母,并且编译器将理解它必须将此字符代码存储在char中。

我的意思是(例如)您不必做

char c = '\0';

要将代码0存储在char中,只需执行以下操作:

char c = 0;

由于我们经常需要处理一堆可变长度的字符,因此C设计人员还选择了"字符串"的约定。只需在文本结尾处输入代码0。顺便说一句,这种字符串表示形式有一个名称"零终止字符串",如果您在变量名的开头看到两个字母sz,则通常意味着它的内容是一个零终止字符串。

" C sz字符串"根本不是一种类型,只是像正常的char数组(例如int数组)一样,但是字符串操作函数(strcmp,strcpy,strcat,printf和许多其他函数)可以理解并使用0结尾约定。这也意味着,如果您有一个不以零结尾的char数组,则不应调用这些函数中的任何一个,因为它可能会做错事情(或者您必须格外小心,并使用名称以字母开头的函数,例如strncpy )。

该约定的最大问题是在许多情况下效率低下。一个典型的例子:您想在0终止的字符串的末尾放置一些内容。如果保持大小,则可以使用sz约定跳到字符串的末尾,必须逐字符检查它。处理编码的unicode或类似代码时会发生其他类型的问题。但是在创建C时,这个约定非常简单并且可以完美地完成工作。

如今,双引号(如" string")之间的字母不再像过去一样是纯字符数组,而是const char *。这意味着指针指向的是一个不应修改的常量(如果要修改它,则必须先复制它),这是一件好事,因为它有助于在编译时检测许多编程错误。

+1,但对于nitpick,字符串文字(即"hi")的类型不是const char*,而是const char[3],其中3是字符数+ 1,表示尾随0。它可以直接当数组衰减为指向第一个元素的指针时分配给const char*,但是此简单测试将显示差异:assert( sizeof(const char*) != sizeof("Hi there!") )

@David Rodrguez-dribeas:是的,您是对的,但是我相信我的答案已经足够复杂,而无需添加有关数组类型和指针之间差异的详细信息。对于那些对此主题感兴趣的人,我尝试在该答案中进行解释:stackoverflow.com/questions/3613302/

终止null在那里终止字符串。没有它,您需要其他方法来确定其长度。

您可以使用预定义的长度:

char s[6] = {'s','t','r','i','n','g'};

您可以模拟Pascal样式的字符串:

unsigned char s[7] = {6, 's','t','r','i','n','g'};

您可以使用std::string(在C ++中)。 strike>(因为您对std :: string不感兴趣)。

最好使用一些已有的处理Unicode的技术,或者至少了解字符串编码(即wchar.h)。

并提供一条评论:如果将其放入旨在在实际计算机上运行的程序中,则可以考虑对自己的"字符串"进行类型定义。如果您不小心尝试将其传递给需要C样式字符串的函数,则这将鼓励您的编译器使用barf。

typedef struct {

char[10] characters;

} ThisIsNotACString;

+1是迄今为止最完整的答案,主要遗漏的是对char s[3] ="abc";的讨论...

如果您只想定义自己的结构类型,那么将长度与char混合起来以模拟pascal字符串是没有好处的。为len设置一个单独的字段会更清洁。它不会在所有基础内存布局上发生变化,但避免了一些潜在的混乱。

C ++ std::string不是NUL终止的。

P.S:NULL是宏1。 NUL是\0。不要把它们混在一起。

1:C.2.2.3宏NULL

在,,,,,

或是此International中实现定义的C ++空指针常量

标准(18.1)。

NULL和NUL都是说0的好方法。

我希望我可以在脚注中为NULL澄清再加上+1。

@Alexander Rafferty:NUL是空字符 0的名称,而NULL是空指针。在C语言中,通常将其定义为(void*)0,而在C ++语言中,仅定义为0。请注意,区别在于类型,而不是值。

从c ++ 11开始,std :: string以null终止。

为了完整起见,请将其完全钉住。

vector

在C ++中,您可以使用字符串类,而根本不处理null字符。

自C ++ 11起不正确:en.cppreference.com/w/cpp/string/basic_string/data

甚至string类也将其存储为null。如果出于某种原因您绝对不希望在内存中的字符串末尾使用空字符,则必须手动创建一个字符块,然后自己填写。

对于您为什么要执行此操作,我个人无法想到,因为空字符是字符串结尾的信号。如果您也要存储字符串的长度,那么我想您已经节省了一个字节,而无论变量的大小是多少(可能是4个字节),并且可以更快地访问所述字符串的长度。

您想要一个不带空字符的HTTP标头字符串。它们会引起问题。

有些地方,例如微控制器,其存储器存储资源有限。根据存储的字符串数,这可能会产生高开销。

NULL终止的原因是使字符串的处理程序可以确定其长度。如果不使用NULL终止符,则需要通过单独的参数/变量或作为字符串的一部分传递字符串的长度。否则,您可以使用另一个分隔符,只要在字符串本身中未使用分隔符即可。

老实说,我不太了解您的问题,或者实际上是否是一个问题。

在C语言中,通常不会有更简单的解决方案。您可以执行pascal的操作,并将字符串的长度放在第一个字符中,但这有点麻烦,并且会将字符串的长度限制为可以容纳在第一个char空间中的整数的大小。

在C ++中,我肯定会使用std :: string类,该类可以由

#include

作为一个常用的库,几乎可以肯定比滚动自己的字符串类更可靠。

使用std :: string。

还有许多其他方式来存储字符串,但是使用库通常比自己制作更好。我敢肯定,我们都可以想出很多古怪的方式来做没有null终止符的字符串:)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值