为什么对c2.view()的调用会打印出客户ID的ID和名称?
我已经盯着这一段时间,找不到原因。我要么错过了一些非常明显的东西,要么我不明白cstrings是如何工作的:)
Customer.h
#ifndef CUSTOMER_H
#define CUSTOMER_H
class Customer
{
private:
char accountID[6];
char name[30];
public:
Customer();
Customer(char[], char[]);
void view();
Customer operator=(const Customer&);
};
#endif
customer.cpp中
#include <string>
#include <iostream>
#include "Customer.h"
using namespace std;
Customer::Customer()
{
strcpy(accountID, "");
strcpy(name, "");
}
Customer::Customer(char acc[], char n[])
{
strcpy(accountID, acc);
strcpy(name, n);
}
void Customer::view()
{
cout << "Customer name: " << name << endl;
cout << "Customer ID: " << accountID <<endl;
}
Customer Customer::operator=(const Customer& right)
{
strcpy(accountID, right.accountID);
strcpy(name, right.name);
return* this;
}
Driver.cpp
#include <iostream>
#include "Customer.h"
using namespace std;
int main()
{
char id[] = "123456";
char n[] = "Bob";
Customer c1;
Customer c2(id, n);
c1.view();
c2.view();
system("pause");
return 0;
}
输出:
Customer name:
Customer ID:
Customer name: Bob
Customer ID: 123456Bob
Press any key to continue . . .
答案 0 :(得分:4)
您正在传递一个包含七个字符的字符串:
char id[] = "123456"; // one more character for null termination '\0'
但是你的数组的大小为6.所以当你打印accountId
时,你超越'6'
字符并打印出它旁边的任何内容,在这种情况下恰好是name
。
使用std::strings
代替字符数组,可以省去很多麻烦。
答案 1 :(得分:1)
使用C ++ std::string
。你写的是accountID
成员的界限。这个char id[] = "123456";
有七个元素。
在这种情况下发生的是终止空字符首先在name[0]
结束,然后被strcpy (name, n)
覆盖,你得到一个连续的序列123456Bob\0
答案 2 :(得分:1)
因为accoutID是长度6的延迟,当你在n中strcpy时,你覆盖了帐户ID'终结符,它溢出到名称[0]
答案 3 :(得分:1)
strcpy
复制,直到它到达空终止符; \0
因为你没有定义并且你正在运行调试,名称恰好占用了与id相邻的内存,并且也被复制到id的缓冲区中。
如果您要构建发布版,那么您很可能只会在那里发布垃圾邮件。无论哪种方式,如果你使用C字符串,你需要在所有字符串的末尾使用空终结符。
strcpy
的实现类似于;
while (*ptr2 != '\0')
{
// copy string2 into string1's buffer until we reach it's null termintor
*ptr1 = *ptr2
ptr1++;
ptr2++;
}
*(ptr1 + 1) = '\0' // append null terminator
正如您所看到的,它依赖于null终止符,如果它不存在,那么您将获得缓冲区溢出。