How to avoid holistic promotion in C?

It's unclear how to write portable C code using the widescreen API. Consider this example:

#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;
}

Compiling with gcc-6.3.0 using the -Wconversion option gives the following warning:

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;
             ^

To get rid of this warning, we will add (wint_t), for example iswlower((wint_t)wc), but this is not possible. The following example shows why it is incapable.

#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;
}

My question is: how to make this example portable and at the same time avoid the gcc warning.

0
source share
1 answer

To keep things simple, I'm going to assume that the platform / implementation under discussion has the following characteristics:

  • 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 , , char.

, (?) , WEOF, - , , (, errno ).

: , 0xffff UCS-2 UTF-16 ( 16- , ).

+1

Source: https://habr.com/ru/post/1661661/


All Articles