簡體   English   中英

在Windows中編譯的C ++程序產生不同的輸出

[英]C++ program compiled in windows produces different output

我正在解決一個涉及增加計數器並顯示它的問題。 我初始化和遞增變量的方式似乎很正常。 請參閱計數器變量

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char s[5];
    int counter = 1;

    while (cin >> s && (strcmp(s, "*") != 0))
    {
        cout << "Case " << counter++ << ": Hajj-e-A";

        if (s[0] == 'H')
        {
            cout << "kbar\n";
        }
        else if (s[0] == 'U')
        {
            cout << "sghar\n";
        } 
    }
}

但是該程序神秘地顯示了錯誤的結果。 它沒有適當增加從1開始的值。 查看輸出。

Case 1: Hajj-e-Akbar
Case 0: Hajj-e-Asghar
Case 1: Hajj-e-Akbar
Case 0: Hajj-e-Asghar

但是,當我嘗試通過使用Linux的http://www.tutorialspoint.com/compile_cpp_online.php進行編譯和運行時,它產生了正確的結果。 該程序也被在線法官接受。

Case 1: Hajj-e-Akbar
Case 2: Hajj-e-Asghar
Case 3: Hajj-e-Akbar
Case 4: Hajj-e-Asghar

任何人都可以指出其背后的奧秘嗎? 為什么Windows編譯的代碼會產生奇怪的結果? 非常感謝!

這是緩沖區溢出。 最有可能的是,當您在Windows上進行編譯時, counter變量將緊隨內存中的s[5]變量,如下所示:

+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 01 | 00 | 00 | 00 |
+----+----+----+----+----+----+----+----+----+
 \________ s[5] ________/ \____ counter ____/

由於Windows是低位優先的,因此它存儲為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系統是big-endian,這意味着內存的布局應如下所示:

+----+----+----+----+----+----+----+----+----+
| ?? | ?? | ?? | ?? | ?? | 00 | 00 | 00 | 01 |
+----+----+----+----+----+----+----+----+----+

因此,即使您讀了5個字符,最終的空終止符也只會替換已經存在的0。 當然,如果這是原因,那么用6個字符讀起來確實會使事情搞砸。

以及如何解決? 問題在於,要容納長度為n的字符串,字符數組的長度必須為n+1 因此,您可以這樣做:

char s[6];

甚至更好,使用字符串:

std::string s;

(為此,您需要#include <string> 。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM