簡體   English   中英

如何避免在C中使用整數提升?

[英]How to avoid integer promotion in C?

尚不清楚如何使用寬字符API用C編寫可移植代碼。 考慮以下示例:

#include <locale.h>
#include <wchar.h>
#include <wctype.h>
int main(void)
{
  setlocale(LC_CTYPE, "C.UTF-8");
  wchar_t wc = L'ÿ';
  if (iswlower(wc)) return 0;
  return 1;
}

使用-Wconversion選項在gcc-6.3.0中進行編譯會給出以下警告:

test.c: In function 'main':
test.c:9:16: warning: conversion to 'wint_t {aka unsigned int}' from 'wchar_t {aka int}' may change the sign of the result [-Wsign-conversion]
if (iswlower(wc)) return 0;
             ^

為了擺脫這一警告的,我們投來(wint_t)iswlower((wint_t)wc)但這是不可移植。 下面的示例演示了為什么它不可移植。

#include <stdio.h>

/* this is our hypothetical implementation */
typedef signed int wint_t;
typedef signed short wchar_t;
#define WEOF ((wint_t)0xffffffff)

void f(wint_t wc)
{
    if (wc==WEOF)
      printf("BUG. Valid character recognized as WEOF. This is due to integer promotion. How to avoid it?\n");
}
int main(void)
{
    wchar_t wc = (wchar_t)0xffff;
    f((wint_t)wc);
    return 0;
}

我的問題是:如何使此示例具有可移植性,同時避免出現gcc警告。

為了簡單起見,我將假設我正在討論的平台/實現具有以下特征:

  • 二進制補碼整數類型
  • int是32位
  • short是16位

我也將使用C99作為參考,因為這是我已經打開的內容。

該標准說,這些類型/宏必須滿足以下條件:

  • wint_t必須至少具有一個與擴展字符集的任何成員都不對應的值(7.24.1 / 2)
  • WEOF的值與擴展字符集的任何成員都不對應(7.24.1 / 3)
  • wchar_t可以表示最大擴展字符集(7.17 / 2)的所有值

請記住,根據C標准對“值”的定義, (short int) 0xffff的值與(int) 0xffffffff的值相同 -也就是說,它們都具有值-1 (假設在此答案的開頭)。 通過標准對整數促銷(6.3.1.1)的描述可以清楚地看出這一點:

如果一個int可以表示原始類型的所有值,則該值將轉換為int; 否則,它將轉換為unsigned int。 這些稱為整數促銷。 整數促銷未更改所有其他類型。

整數促銷保留包括符號在內的價值。

我相信,當您將這些元素組合在一起時,似乎WEOF的值為-1 ,那么擴展字符集中的任何項目都不能值為-1 我認為這意味着在您的實現示例中,要么wchar_t必須是無符號的(如果它仍然是16位類型),要么(wchar_t) 0xffff不能是有效字符。

但是我最初忘記的另一種選擇(可能是您的示例實現的最佳解決方案)是,標准在腳注中指出“宏WEOF值可能與EOF值不同,不必為負”。 因此,可以通過使WEOF == INT_MAX來解決實現問題。 這樣,它不能具有與任何wchar_t相同的值。

我認為可能與有效字符值重疊的WEOF值是我認為可能在實際實現中出現的一個值(即使該標准似乎禁止了它),它類似於關於EOF可能與某些值具有相同值的問題。有效的帶符號字符值。

對於大多數可以返回WEOF來指示某種問題的(全部?)函數,可能有意思的是,標准要求該函數設置有關錯誤或條件的一些附加指示(例如,將errno為特定值,或在流上設置文件結束指示符)。

需要注意的另一件事是,根據我的理解,0xffff在UCS-2或UTF-16中是非字符(不知道可能存在的其他任何16位編碼)。

暫無
暫無

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

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