簡體   English   中英

確定字符串是否是C中的有效wchar_t *

[英]Determine if a string is a valid wchar_t* in C

我正在嘗試重新編寫printf的一部分。

setlocale(LC_ALL, "en_US.UTF-8");
int ret = printf("%S\n", "我是一只貓。");
printf("Printf returned %d\n", ret);

如果格式為%s ,則printf寫入寬字符並返回19。

如果格式為%S ,則printf返回-1,因為參數不是寬字符串(在“”之前沒有L )。

在我自己的printf實現中,如何確定參數中傳遞的字符串是否寬,所以如果不是,我可以返回-1?

編輯

  • 我正在使用OS X El Capitan進行編程(但如果有可能,我會想要一個可移植的解決方案)
  • 在我的編程環境中,%S和%ls是相同的 - 這對我的問題並不重要
  • 當我沒有為格式為%s的示例設置區域設置時,Printf也返回-1。 這是我設置語言環境的唯一原因。
  • 我正在使用clang編譯( Apple LLVM版本7.0.0(clang-700.1.76)

基本上,你不能。 傳遞對於%S不是寬字符串的東西是未定義的行為,任何事情都可能發生,包括飛出你鼻子的dæmons。 你是幸運的, printf捕捉的是,有可能檢測到的內容, "我是一只貓。"當解釋為數組wchar_t是不是所有的有效代碼點(如果出現這種情況, errno設置為EILSEQ通過printf )。

在我自己的printf實現中,如何確定參數中傳遞的字符串是否寬,所以如果不是,我可以返回-1?

你不能。 %S格式說明符在printf(3)中記錄

(不是在C99或C11中,而是在SUSv2,SUSv3和SUSv4中。) %ls同義詞。 不要用。

所以你可能不應該使用它(因為它符合C11標准,但是在SUSv4中)。 如果你沒有使用你自己printf ,這將是一個承諾 ,相應的實際參數一個寬字符串。

但是,如果您的C編譯器是最近的GCC ,則可以在printf (或類似)函數的聲明中使用適當的format 函數屬性 (它是GCC擴展名)。 這會向用戶發出警告,告知用戶函數的錯誤類型參數。 你甚至可以通過定義自己的函數屬性來自定義GCC(例如使用MELT ),這將在編譯時啟用額外的類型檢查,因此在給定指針的情況下沒有可移植的方法在運行時檢查它是否是指針到一個字符串或其他東西(如整數數組)。

在運行時,您的printf將使用stdarg(3)工具,因此必須“解釋”格式字符串以適當處理各種格式說明符。 如果沒有編譯器支持( __attribute__((format(printf,1,2)))在GCC中(也由Clang支持 ),或者使用您自己的函數屬性),您無法獲得任何編譯時類型檢查可變參數函數。 並且類型信息在運行時在C中被擦除。

另請參閱C標准庫的 自由軟件實現中類似printf 現有實現。 MUSL libcstdio/vfprintf.c文件非常易讀。

此外, GNU libunistring有一些基本的字符串檢查函數 ,例如u16_check ,它檢查16位整數的數組(給定其大小)是否是有效的UTF16字符串。 請注意,UTF8中的"我是一只貓。" 不是零雙字節或零寬度終止的UTF16字符串(所以簡單地計算其長度為wchar_t*寬字符串是未定義的行為 ,因為緩沖區溢出 !)甚至可能不均勻具有寬字符串所需的對齊方式。

暫無
暫無

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

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