簡體   English   中英

GCC 和 MSVC 中的 C++ utf-8 文字

[英]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 使用松散的規則並以更實用的“現實世界”方式實現標准

所以在 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.

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