在我的代碼中,我使用日志記錄陳述句以便更好地了解發生了什么。有時我會撰寫如下代碼:
int i = 1337;
// More stuff...
logger->info("i has the following value: " i);
在除錯模式下編譯和執行時,它不會i
按預期列印出來(例如,它在 Java/C# 中的作業方式),而是列印出一些亂碼。然而,在發布模式下,這可能會使整個應用程式崩潰。C
標準對將整數附加到std::string
我在這里做的事情有什么看法?
為什么當我編譯像這樣呼叫明顯未定義行為的代碼時,編譯器根本不會警告我?我錯過了什么嗎?我正在使用 Visual Studio 2022 (MSVC)。執行日志記錄陳述句的正確方法是將 intstd::string
顯式轉換為:
logger->info("i has the following value: " std::to_string(i));
然而,這個錯誤在開發程序中很容易漏掉。我的警告級別設定為Level4 (/W4)
。
uj5u.com熱心網友回復:
問題是在
logger->info("i has the following value: " i);
您沒有使用 std::string。您正在添加一個字串文字,即 aconst char *
和 an int
。這是做什么的,它將指標推進了 1337,這超出了字串文字的結尾,因此是未定義的行為。
你應該得到一個更好的編譯器:
foo.cc:7:42: warning: offset ‘1337’ outside bounds of constant string [-Warray-bounds]
7 | foo("i has the following value: " i);
| ^
您可以像這樣使用 std::string 文字:
#include <string>
using namespace std::literals;
void foo(std::string);
void bla() {
int i = 1337;
foo("i has the following value: "s i);
}
然后你會得到一個“不錯的”錯誤,即“std::string int”在 c 中不是一個東西:
foo.cc:8:40: error: no match for ‘operator ’ (operand types are ‘std::__cxx11::basic_string<char>’ and ‘int’)
8 | foo("i has the following value: "s i);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~
| | |
| std::__cxx11::basic_string<char> int
...
going on for 147 lines
在此之后,你想要的是顯而易見的:
logger->info("i has the following value: "s std::to_string(i));
使用 std::string 文字可以避免這樣的錯誤,因為它會將警告(您的編譯器甚至沒有給出)變成硬錯誤,迫使您撰寫正確的代碼。所以我建議s
對所有字串使用后綴。
uj5u.com熱心網友回復:
這條線是正確的,
logger->info("i has the following value: " i);
在運算式中
"i has the following value: " i
這里使用了指標演算法。
例如,如果你會寫
logger->info("i has the following value: " 6);
那么這一行如果寫成同樣的效果
logger->info("the following value: ");
就是這條線
logger->info("i has the following value: " i);
相當于線
logger->info( &"i has the following value: "[i]);
C 標準對像我在這里做的那樣將整數附加到 std::string 有什么看法
在運算式中沒有型別的物件std::string
。使用了一個字串文字,它只有一個普通的陣列型別,它是具有指標運算的運算式的運算元。在運算式中,字串文字被隱式轉換為指向其型別的第一個元素的指標const char *
。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/470835.html