[英]C++ utf-8 literals in GCC and MSVC
這里我有一些簡單的代碼:
#include <iostream>
#include <cstdint>
int main()
{
const unsigned char utf8_string[] = u8"\xA0";
std::cout << std::hex << "Size: " << sizeof(utf8_string) << std::endl;
for (int i=0; i < sizeof(utf8_string); i++) {
std::cout << std::hex << (uint16_t)utf8_string[i] << std::endl;
}
}
我在這里看到 MSVC 和 GCC 的不同行為。 MSVC 將"\\xA0"
視為未編碼的 unicode 序列,並將其編碼為 utf-8。 所以在 MSVC 中,輸出是:
C2A0
在 utf8 unicode 符號U+00A0
中正確編碼。
但是在 GCC 的情況下不會發生任何事情。 它將字符串視為簡單字節。 即使我在字符串文字之前刪除u8
也沒有任何變化。
如果字符串設置為: u8"\ ";
則兩個編譯器都編碼為帶有輸出C2A0
的 utf8。
為什么編譯器的行為不同,實際上哪個是正確的?
用於測試的軟件:
海合會 8.3.0
MSVC 19.00.23506
C++ 11
他們都錯了。
據我所知,C++17 標准在這里說:
窄字符串文字的大小是轉義序列和其他字符的總數,加上至少一個用於每個通用字符名稱的多字節編碼,加上一個用於終止的 '\\0'。
盡管還有其他提示,但這似乎是轉義序列不是多字節並且 MSVC 的行為錯誤的最有力的跡象。
有針對此的票證,目前標記為“正在調查”:
然而,它也在這里說關於 UTF-8 文字:
如果該值不能用單個 UTF-8 代碼單元表示,則程序格式錯誤。
由於0xA0
不是有效的 UTF-8 字符,因此程序不應編譯。
請注意:
u8
開頭的 UTF-8 文字被定義為窄的。\\xA0
是一個轉義序列\
被認為是通用字符名稱而不是轉義序列為什么編譯器的行為不同,哪個實際上是正確的?
編譯器的行為不同,因為它們決定實現 C++ 標准的方式:
所以在 GCC 中失敗的事情通常會在 MSVC 中工作,因為它更被允許。 MSVC 會自動處理其中一些問題。
這是一個類似的例子: https : //gcc.gnu.org/bugzilla/show_bug.cgi?id=33167 。 它遵循標准,但不是您所期望的。
至於哪個做得對,取決於您對“正確”的定義是什么。
我不能告訴你哪種方式符合標准。
MSVC 的做法至少在邏輯上是一致且易於解釋的。 三個轉義序列
\\x
、 \\u\u003c/code>和
\\U
行為相同,除了它們從輸入中提取的十六進制數字的數量:2、4 或 8。每個都定義了一個 Unicode 代碼點,然后必須將其編碼為 UTF-8。 嵌入一個沒有編碼的字節會導致創建無效的 UTF-8 序列的可能性。
這是CWG 問題 1656 。
在當前的標准草案中通過P2029R4解決了這個問題,以便將數字轉義序列的值視為單個代碼單元,而不是作為然后編碼為 UTF-8 的 unicode 代碼點。 即使它導致無效的 UTF-8 序列也是如此。
因此 GCC 的行為是/將是正確的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.