2016-01-01 34 views
1

我只是瀏覽四處尋找的UTF-8代碼點一些實現(不,不是抄襲)和跨this偶然發現:這個UTF-8實現是實現定義的還是定義明確的?

typedef unsigned char char8_t; 
typedef std::basic_string<unsigned char> u8string; 

這段代碼竟然無視CHAR_BIT只有要求至少爲8,但可能會更大?或者在這種情況下這不重要,代碼很好?如果是這樣,那爲什麼是這樣呢?

另外,有些人(?想必SO成員@NicolBolas)寫了:

const char *str = u8"This is a UTF-8 string."; 

這是非常如何UTF-8將在C++中用於字符串文字。

我以爲UTF-8中的代碼單元總是正好8位!
從Unicode標準8.0.0,第2.5章:

在Unicode字符編碼模型,精確定義的編碼 形式指定一個Unicode字符的每個整數(代碼點)是如何 被表示爲一個一個或多個代碼單元的序列。 Unicode 標準爲Unicode 字符提供了三種不同的編碼形式,使用8位,16位和32位單元。這些是 ,分別命名爲UTF-8,UTF-16和UTF-32。

(換行符去掉,就斷行連字符去掉,加上強調)

那麼,爲什麼他要求const char*是用來代替const uint8_t*(或建議的,假設const char8_t*)?

+0

@skypjack我回到我的版本。第一個代碼是一個引號,即使沒有真正的文本。 – Downvoter

+0

這麼好的一個問題,但是引號中幾乎沒有視覺缺陷,所以我刪除了它們,沒有更多。我錯了,這是我的移動應用程序沒有正確格式化問題? – skypjack

+0

@skypjack呃......它看起來不太好,讓我們用外交的方式來說吧。 :-) – Downvoter

回答

1

那麼,爲什麼他要求const char*是用來代替const uint8_t*(或建議的,假設const char8_t*)?

因爲這就是標準所說的。一個u8文字字符串將解析爲const char[N]類型的數組。這就是C++中UTF-8文字的定義。

如果一個系統上的char有超過8位......就這樣吧。字符串中的每個char仍將保持0到255之間的值,這是有效UTF-8代碼單元的範圍。儘管char可以在這樣的系統上保持較大的值。如果char不能持有8位...則執行無效。按照最近的標準措辭,需要char來保存足夠的位以存儲每個有效的UTF-8代碼單元。從技術上講,255不是有效的UTF-8編碼單元。

而事實是這樣的:已經有巨大的通過char*接受UTF-8的代碼量。他們不會重寫POSIX,文件系統API以及其他採用不同類型的其他方法。

這就是說,通過const char*來操縱一系列UTF-8代碼單元是......可疑的。這是因爲他們可以簽字。但是,最近的標準措辭要求在unsigned charchar之間的轉換在有效的UTF-8代碼單元範圍內工作。也就是說,您可以將const char*投射到const unsigned char*,對其進行操縱,然後將其投回,並保證能夠正常工作。

那個超級複雜的「最近的標準措辭」是什麼意思?

這一點的目的是讓UTF-8字符串實際上工作。因爲標準委員會以其「無限智慧」決定不包含特殊的UTF-8編碼單元類型,所以他們不得不添加措辭以使char成爲該角色。這就要求將unsigned charchar之間的轉換不能破壞UTF-8代碼單元。

甚至有一個discussion topic on the C++ standard discussion forums,其中wording was discussed (search for 1759)。在C++ 14措詞說:

對於範圍內unsigned char類型的每個值i 0到255以下,存在類型的值jchar使得從i一個整體轉化率(4.7)的結果到charj,並且從junsigned char的積分轉換的結果是i

這意味着特別是char只有在符號表示滿足上述條件時纔可以默認簽名。一個一補簽署char是不夠的,因爲負零有一個特殊的表示(0x80的),當其轉換爲無變爲定期0的。如果他們剛剛定義的要求是無符號並具有特定char8_t

至少8位?大概。但它已經完成,並沒有改變。

+0

」從技術上講,255不是有效的UTF-8代碼單元。「什麼。 '255'適合8位,所以爲什麼不用UTF-8編碼單元呢?那個超級複雜的「標準最近措詞」是什麼意思?而且,對於位操作,你是什麼意思?我認爲'const char *'在取消引用時不允許修改。 – Downvoter

+0

爲什麼'char'而不是'unsigned char'?如果'char'被簽名了怎麼辦?這不是實現定義的行爲嗎? – Downvoter

+1

'255適合8位,那爲什麼不用UTF-8編碼單元呢?'如果你看一下UTF-8編碼的細節,那麼每個可以成爲有效UTF-8序列的八位字節將至少有一個0位在它。我認爲最大的八位字節是'11110111b == 247' –

1

[lex.string]/8普通字符串和UTF-8字符串文字也稱爲窄字符串文字。窄字符串文字的類型爲「數組爲n const char」,其中n是下面定義的字符串的大小,並且具有靜態存儲持續時間(3.7)。

因此,無論其他情況如何,UTF-8字符串文字都是一系列的char s。

至於uint8_t

7.20.1.1

2 typedef名uintN_t表示具有寬度N和沒有填充比特的無符號整數類型。因此,uint24_t表示寬度恰好爲24位的這種無符號整數類型。

3這些類型是可選的。但是,如果實現提供寬度爲8,16,32或64位的整數類型,沒有填充位,並且(對於有符號類型)具有二進制補碼錶示,則它應該定義相應的typedef名稱。

在帶char大於8位的假想系統,uint8_t不會被限定。

+0

好吧,這是標準的版本,但爲什麼呢?爲什麼UTF-8字符串合法地被稱爲「const char *」? – Downvoter

+0

因爲缺乏更好的選擇,我會假設。你會如何定義它呢? –

+0

「在char大於8位的假設系統上,不會定義uint8_t。」我詢問這個​​事實在聊天中是否屬實(Lounge ),他們告訴我這是錯誤的,因爲一些實現定義可以用來實現'uint8_t'。 – Downvoter

3

uint8_t只存在於可以訪問的存儲器的系統上,正如正好是 8位。 UTF-8沒有任何這樣的要求。它使用適合8位的值,但不對這些值實際存儲的方式施加任何要求。每個8位值可以存儲爲16位或32位,或者對於正在運行的系統有意義;唯一的要求是該值必須正確。

+0

我可以'我們用一個UTF-8字符串,每個代碼單元是8位,現在將它存儲在RAM中,每個字節都是** 9 **位,這些不同的字節單元不會重疊並導致大量的災難? – Downvoter

+0

@cad:當然不是,如果你把這個字符串存儲在9位字節存儲器中,每個字符仍然存儲在一個單獨的字節中 – chqrlie

+0

@cad - 不,這不是問題如果內存組織爲9編譯器在3個9位塊中存儲3個8位值,這3個值不受存儲方式的影響 –

0

UTF-8中的代碼單位始終正好是8位。指定unsigned char至少有8位,所以UTF-8中的所有代碼單元都適合unsigned char

u8"This is a UTF-8 encoded string constant"的基本原理不是它存儲在8位字節中,而是它被編碼爲UTF-8,而源文件可能有不同的編碼。 typedef與此一致,但如果字節超過8位,則會引起混淆。

使用unsigned char是消除關於char類型的簽名性的不確定性的好方法。