我用C最近已经开始编程,从Java和Python的到来。 现在,在我的书,我已经注意到了,做一个“Hello World”程序,语法是这样的:
char message[10]
strcpy(message, "Hello, world!")
printf("%s\n", message);
现在,这个例子是使用字符数组,我不知道 - 发生了什么条件? 为什么我不能简单地用其中的一个? 也许有不同的方式来做到这一点?
我用C最近已经开始编程,从Java和Python的到来。 现在,在我的书,我已经注意到了,做一个“Hello World”程序,语法是这样的:
char message[10]
strcpy(message, "Hello, world!")
printf("%s\n", message);
现在,这个例子是使用字符数组,我不知道 - 发生了什么条件? 为什么我不能简单地用其中的一个? 也许有不同的方式来做到这一点?
C不和从未有过本地字符串类型。 按照惯例,语言使用的阵列char
用一个空字符,即终止, '\0'
。 在该语言的标准库函数和宏提供用于空终止字符数组,例如,支持的strlen遍历的阵列char
直到遇到'\0'
字符和strcpy的从源串拷贝直到遇到'\0'
。
使用用C零结尾的字符串反映了下意图是只有一点点多层次的高比汇编语言。 零终止字符串已经直接支持在当时的PDP-10和PDP-11的汇编语言 。
值得一提的是,C字符串的这一特性导致了相当多的讨厌的缓冲区溢出漏洞,其中包括严重的安全漏洞。 例如,如果你忘了空-终止作为源参数传递给一个字符串strcpy
,该函数将继续从任何恰好是在内存过去的源字符串的结束,直到它恰好遇到一个复制连续字节0
,可能改写任何有价值的信息如下内存中的目标字符串的位置。
在你的代码示例中,字符串文字“你好,世界!” 将汇编成的一个14字节长的阵列char
。 第一个13个字节将持有的字母,逗号,空格和感叹号和最后一个字节将持有空终止字符'\0'
,编译器为你自动添加。 如果你要访问数组的最后一个元素,你会发现它等于0
。 例如:
const char foo[] = "Hello, world!";
assert(foo[12] == '!');
assert(foo[13] == '\0');
然而,在你的榜样, message
仅是10个字节长。 strcpy
会写所有14个字节,包括空终止,到存储器中,起始的地址message
。 的前10个字节将被写入栈上分配的内存message
,其余四个字节将被简单地写入到栈的末端。 写这四个额外字节到堆栈的后果是很难在这种情况下,预测(在这个简单的例子,它可能不会伤害的事情),但在现实世界中的代码,它通常会导致损坏的数据或内存访问冲突错误。
有没有string
型C
。 你必须使用字符数组。
顺便说你的代码将无法正常工作,因为数组的大小应该允许整个阵列,以适应外加一零个终止字符。
在C中,一个字符串简单地是字符数组,以空字节结束。 因此,一个char*
常常发音“弦”,当你阅读的C代码。
要注意的是在你所提到的语言:
Java的:
String str = new String("Hello");
蟒蛇:
str = "Hello"
无论是Java和Python有一个“串”,C没有“串”的概念的概念。 C有字符数组,可以进来“只读”或可操作。
C:
char * str = "Hello"; // the string "Hello\0" is pointed to by the character pointer
// str. This "string" can not be modified (read only)
要么
char str[] = "Hello"; // the characters: 'H''e''l''l''o''\0' have been copied to the
// array str. You can change them via: str[x] = 't'
的字符数组是连续的字符,其中所述端部(通常是NULL终止子的独特标记字符的序列'\0'
)。 请注意,标记字符是自动奇迹般地在上述情况下,附加给你的。
C不支持一流的字符串类型。
C ++拥有的std :: string
C没有像Java自身的字符串数据类型。
只有我们可以使用字符数组或字符指针例如声明在C字符串的数据类型:
char message[10];
or
char *message;
但是,你需要至少声明:
char message[14];
复制“你好,世界!” 为消息变量。
首先,你不需要做这一切。 特别是, strcpy
是多余的-你不需要复制字符串只是printf
它。 您的message
可与地方的字符串来定义。
其次,你不允许足够的空间为“你好,世界!” 字符串( message
需要是至少14个字符,从而允许额外的一个空终止)。
关于为什么,但是,它的历史。 在汇编时,不存在字符串,仅字节,字等等帕斯卡有字符串,但也有与由于其静态类型的问题- string[20]
是一个不同类型的string[40]
甚至有在创业初期即避免了这个问题的语言,但间接造成的,哪些更多的效率问题的当年动态分配开销。
Ç只需选择避免开销并保持非常低的水平。 字符串是字符数组。 数组是很密切的关系指向他们的第一项指针。 当数组类型“衰减”为指针类型,缓冲区大小的信息是从静态类型丢失,所以你没有得到老帕串的问题。
在C ++中,有个std::string
类,它避免了大量的这些问题-并且具有动态分配的开销,但这些天我们通常不关心这个。 在任何情况下, std::string
是一个库类-有C风格字符数组处理的下方。