这是缓冲区溢出。最有可能的是,当您在 Windows 上编译时,counter 变量紧跟在内存中的 s[5] 变量之后,如下所示:
+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
\________ s[5] ________/ \____ counter ____/
由于 Windows 是 little-endian,它存储为 01 00 00 00 而不是您可能期望的 00 00 00 01。 ?? 只是表示我们还不知道那里有什么——它可能是任何东西。
现在,假设您输入“Hardy”并按 Enter。在 ASCII 中,它转换为字节序列 48 61 72 64 79 0D 0A(最后两个是行尾,在 UNIX 上,0D 将被省略)。这就是cin >> s 对内存的作用:
1. Read in 'H':
+----+----+----+----+----+----+----+----+----+
| 48 | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
2. Read in 'a':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
3. Read in 'r':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
4. Read in 'd':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
5. Read in 'y':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | 79 | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
6. Read in '\r\n' (or on UNIX, just '\n'), but this isn't put into the memory.
Instead, cin realizes that it has finished reading, and closes off the string with a '\0':
+----+----+----+----+----+----+----+----+----+
| 48 | 61 | 72 | 64 | 79 | 00 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
\________ s[5] ________/ \____ counter ____/
哎呀!它覆盖了计数器!
为什么它可以在 Linux 上正常工作?要么 Linux 没有将这两个变量相邻放置在内存中,要么 Linux 系统是大端的,这意味着内存的布局是这样的:
+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 00 | 00 | 00 | 01 |
+----+----+----+----+----+----+----+----+----+
因此,即使您读入 5 个字符,最终的空终止符也只会替换已经存在的 0。当然,如果是这个原因,那么读入 6 个字符就真的很麻烦了。
你如何解决它?问题是,要保存长度为n 的字符串,字符数组的长度必须为n+1。所以你可以这样做:
char s[6];
或者更好的是,使用字符串:
std::string s;
(为此您需要#include <string>。)