简体   繁体   English

c ++字符串行为在定义时和在strcat函数中均不同

[英]c++ string behaviour is different while defining and in strcat funtion

#include <iostream>
#include <cstring>
using namespace std;
int main ()
{
    char str1[10] = "Hello";
    char str2[10] = "World";
    int  len ;
    strcat( str1, str2);
    len = strlen(str1);
    cout << len << endl<<str1<<endl;
    return 0;
}

When i initialize str1 like this char str1[5]="hello"; 当我像这样初始化str1 char str1[5]="hello"; , C++ compiler gives me an error (means the size of the string must be 1 more than the given string). ,C ++编译器给我一个错误(表示字符串的大小必须比给定的字符串大1)。 But in the strcat we are concatenate str1 with str2 with the size of the first string is 10 and length of the string is also 10 (means no extra null character) . 但是在strcat我们将str1str2串联在一起,第一个字符串的大小为10,字符串的长度也为10(表示没有多余的null字符)。 Why is this changing behavior ? 为什么这种变化的行为? Are we converting C++ string with C string in strcat function, please explain. 我们要在strcat函数中用C字符串转换C ++字符串strcat ,请解释。

Are we converting c++ string 我们是否在转换c ++字符串

No, there are no c++ strings (ie std::string ) involved in your program. 不,您的程序中没有c ++字符串(即std::string )。

why is this changed behavior ? 为什么这会改变行为?

You wrote a different program, and the behaviour is different. 您编写了另一个程序,其行为也有所不同。

In the first case, your program was ill-formed. 在第一种情况下,您的程序格式错误。 The standard requires the compiler to notify you of this at compile time. 该标准要求编译器在编译时通知您。 And detecting your bug is easy for the compiler as well. 而且,对于编译器来说,检测错误也很容易。 The type of the variable is "array of 5 characters". 变量的类型为“ 5个字符的数组”。 6 characters won't fit - the type is wrong. 6个字符不合适-类型错误。 Types are known at compile time. 类型在编译时是已知的。


In the example code, you use strcat . 在示例代码中,使用strcat If you take a look at this reference you'll find that 如果您查看此参考资料 ,将会发现

The behavior is undefined if the destination array is not large enough for the contents of both src and dest and the terminating null character. 如果目标数组的大小不足以容纳src和dest的内容以及终止的空字符,则该行为不确定

Standard doesn't require the compiler to warn you about undefined behaviour. Standard不需要编译器警告您未定义的行为。 In fact, it is usually quite difficult for the compiler to prove that a program has undefined behaviour - even though in this particular case it seems obvious. 实际上,编译器通常很难证明程序具有未定义的行为-即使在这种特殊情况下看起来很明显。

The arguments of strcat are pointers. strcat的参数是指针。 You pass pointers of correct type to strcat . 您将正确类型的指针传递给strcat There are no type errors. 没有类型错误。 The bug is in the wrong values. 错误是在错误的值。 The values are copied into the arrays at run time (unless the optimizer does some magic). 将这些值在运行时复制到数组中(除非优化程序做了一些魔术)。 To figure out your bug, the compiler would have to simulate the execution of the program. 为了找出您的错误,编译器必须模拟程序的执行。 Doing that for all code paths would be extremely slow. 对所有代码路径执行此操作将非常慢。 So, the compiler leaves the responsibility to the programmer to satisfy the preconditions of strcat . 因此,编译器将责任交给程序员,以满足strcat的前提。

These are C-style strings, not C++ strings, ie, you are not using the std::string class. 这些是C样式的字符串,而不是C ++字符串,也就是说,您没有使用std :: string类。 C-style strings are terminated by '\\0', which means you need an extra storage location beyond the length of the string. C风格的字符串以'\\ 0'终止,这意味着您需要一个超出字符串长度的额外存储位置。 "Hello" has a length of 5, but you need an array of size 6 to store it. “ Hello”的长度为5,但是您需要一个大小为6的数组来存储它。 In your example, it is not actually necessary to specify the size of the arrays, just do the following and let the compiler calculate the size: 在您的示例中,实际上没有必要指定数组的大小,只需执行以下操作并让编译器计算大小即可:

char str1[] = "Hello";

The strcat function requires that the first argument points to an array that has sufficient space for the concatenated string. strcat函数要求第一个参数指向一个数组,该数组具有足够的空间用于连接的字符串。 It is a dangerous function because it will not check whether this is actually the case, if not, it will simply overwrite whatever is beyond the end of your array. 这是一个危险的函数,因为它不会检查是否确实存在这种情况,否则,它只会覆盖数组末尾的所有内容。 In your case, concatenating two strings that are each 5 characters long, you will get a string that is 10 characters long, and you need to make sure that the first argument points to an array that is at least 11 characters long. 在您的情况下,连接两个长度分别为5个字符的字符串,您将得到一个长度为10个字符的字符串,并且需要确保第一个参数指向一个至少11个字符长的数组。 If you were using C++ strings you would not have to worry about any of this: 如果您使用的是C ++字符串,则无需担心以下任何一项:

#include <string>
#include <iostream>

int main()
{
   std::string str1("Hello");
   std::string str2("World");
   str1.append(str2);
   std::cout << str1.size() << '\n' << str1 << std::endl;
}

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

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