gpt4 book ai didi

c - 如何避免C中的整数提升?

转载 作者:行者123 更新时间:2023-11-30 14:58:59 24 4
gpt4 key购买 nike

目前尚不清楚如何使用宽字符 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) 清楚地表明了这一点:

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions.

The integer promotions preserve value including sign.

我相信,当您组合这些元素时,如果 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 位编码)。

关于c - 如何避免C中的整数提升?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43061489/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com