繁体   English   中英

为什么以及何时必须在C ++中使用之前初始化字符串?

[英]Why and when do we have to initialize a string before using in C++?

我正在阅读一些C ++教程,发现有时会初始化字符串(“ initialized”可能不是正确的术语),有时却没有。

为什么以及何时?

我正在阅读的代码是:

char name[50];
char lastname[50];
char fullname[100];
...
cin.getline ( name, 50 );
...
cin.getline ( lastname, 50 );
fullname[0] = '\0';            // strcat searches for '\0' to cat after
strcat ( fullname, name );     // Copy name into full name
strcat ( fullname, " " );      // We want to separate the names by a space
strcat ( fullname, lastname ); // Copy lastname onto the end of fullname

请有人解释。

在C ++中,有字符数组,如char name[50] ,还有字符串类,如std::string

字符数组根据它们在C中的相同规则进行初始化-也就是说,如果它们是堆栈变量,则不进行初始化;如果是静态/全局变量,则在加载时将其初始化为零-但是有例外基于系统细节,因此最好是假设它们从未初始化。

字符串类(如std :: string)在对象的构造函数阶段被初始化-因此它们总是被初始化。

在您的特定代码中,您正在使用固定长度的字符数组。 它们通常以null终止,但可能并不总是-特别是cin.getline ( name, 50 ); 将读取完整的50个字符,并且如果输入的字符数少于或等于49个,则该数据将以null终止,但是由于没有空间可容纳50个以上的字符,因此如果输入的字符数为50个或更多,则不会以null终止-这会对您的strcat产生影响,因为strcat假定数据以null结尾-您必须使用strncat来确保代码安全。

与其他任何数据类型一样。 默认情况下,局部变量包含垃圾值。 因此,如果要读取其值,则可以对其进行初始化。 但是,如果您知道将要写入变量,则可以跳过初始化部分。

例如:

char a[20]; //local variable

包含垃圾,因此您需要在读取之前向其中写入一些有意义的数据。 但是,如果您只写它,则可以跳过初始化。

您所拥有的在堆栈上有一个分配。 编译器不保证分配的内存为空,因此您可以在其上放置垃圾,这就是为什么您需要填充0来清除垃圾的原因。

你可以做到

memset(pointer, '0', size);

char a[50]

memset(a, NULL, sizeof(char)*50);

当取决于您的操作时,如果您想在其中写入一些数据并进行读取,则\\ 0可能会节省您的时间,因为这是截止日期;如果您想读取所有数据,则将50字节char a [50]设置为char忽略\\ 0,因此您需要清除数据。 解决方法是清除^^内部的数据。

first_namelast_name不会立即初始化,因为接下来的两行会在after和full_name到0终止符后立即对其进行初始化,因此它将表示一个空字符串,可以将其与std :: strcat连接。

char first_name[50];
char last_name[50];

// There is no need to initialize first_name and last_name,
// they will contain garbage as with any uninitialized values but they get
// overwritten here when reading from stdin anyways.
cin.getline ( first_name, 50 );
cin.getline ( last_name, 50 );

char full_name[100];
// Again full_name contains garbage, so it gets a 0 terminator here in order
// to have it represent an empty string.
full_name[0] = '\0';

// full_name had to be an empty string in order to concatenate
// onto it using strcat
strcat ( full_name, first_name );
strcat ( full_name, " " );
strcat ( full_name, last_name );

话虽这么说,这些都是C样式的字符串,您很可能更喜欢只使用std::string

cin.getline不使用或检查您传入的缓冲区的原始值,因此对于该功能,无需初始化缓冲区。

相比之下, strcat检查现有缓冲区的内容,以确定应在指定的字符串字符上附加的位置。 因此,使用strcat ,不仅必须随意初始化缓冲区,而且还必须初始化一些零字节来标记逻辑字符串末尾位置。


正如其他人所说,显示的代码非常不安全。 这是不安全的,因为(我在撰写本文时尚未对此进行评论)维护程序员可能没有意识到full_name具有确切的缓冲区大小来容纳最大长度的名字,空格和最大大小的姓氏。 至少应该在评论中对此进行了解释。

但是比注释更好,应该使用更安全的长度检查功能。

并且除了学习之外,更好的方法是使用诸如std::string类的字符串类。

暂无
暂无

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

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