关于在C中使用扩展符号将char转换为int

时间:2012-11-10 00:35:21

标签: c types integer char type-conversion

我正在阅读Stephen G. Kochan关于C编程的C编程。它声明:

“如果使用的字符值不是标准字符的一部分,则在转换为整数时可能会扩展其符号”

然后说明

“C语言允许声明字符变量无符号,这可以避免这个潜在的问题”

有人可以解释在从char转换为int期间扩展符号时可能出现的问题吗? 为什么这很重要? 一个负整数是什么问题,它被转换为char?

谢谢

2 个答案:

答案 0 :(得分:4)

假设您从< ctype.h>,isupper()中获取无辜的功能。

它定义为int isupper(int c);。所以它需要一个int并返回一个int。

现在,让我们说你不是一个非常谨慎的程序员,你只需要将char传递给这个函数。你自己想:“会出现什么问题?这是我所知道的最简单的功能!”。

但你错了。在某个地方,由于这个可怕的错误,有人会让她的MP3播放器进入无休止的崩溃循环。

这就是原因。 C中最讨厌的类型是char。它可以是签名的,它可以是无符号的,你可以用这种或那种方式强制编译器(但是你打开另一种蠕虫),最糟糕的是,标准的C库在任何地方都使用这种类型!

所以,你使用char,但是你不知道它实际上是在你的环境中签名的。您可以使用它,好像世界是一个ASCII世界。

但世界不是。 MP3快乐的老板现在正在收听一首着名的德国歌曲,其名字中包含字母ä(“扩展的ASCII码132”)。

您将此字符传递给isupper(),编译器会执行以下操作: “啊,这是一个字符,但函数需要一个整数。我知道!我不会警告程序员,因为这太简单了。我只是将字符转换为整数并传递它。我该怎么做?让我们检查一下C标准...嗯...简单,只需取值并对其进行符号扩展(因为char已签名,你不知道吗?)。现在,这个字符的值为-124,所以我'我只是将它转换为一个值为-124的int。这很简单,我看不出大惊小怪。我为什么要警告程序员?!“

现在使用-124而不是132来调用isupper()

但那有什么问题?没有什么,除了编译器附带的C库使用一个简单的128字节数组实现isupper():它只返回给定索引处的值。除了大写的ASCII代码之外,数组初始化为0,其中它是1.这样一个简单而优雅的实现......

但是等一下,如果你把负值传递给这个函数怎么办?嗯,这是不允许的:

  

c参数是一个int,应用程序的值   ensure是一个可表示为unsigned char或等于的字符   宏EOF的值。如果参数有任何其他值,则   行为未定义。

所以,未定义的行为。在这种情况下,它尝试访问不属于该进程的内存,以及BAM!程序崩溃。

所以你看,char是邪恶的,你永远不应该使用它,除非你真的明白如何正确使用它。

(*)正如Keith Thompson在评论中所说,当然不可能避免使用char。从strlen()curl_easy_escape(),每个人都使用char。但是您应该知道转化为int,尤其是当char可能包含负数时。 <文件ctype.h>函数和数组索引是两个容易出错的地方。

答案 1 :(得分:1)

在C中, plain char可以是有符号或无符号的,可以选择实现。

来自 C99,6.2.5,7

  

共有三种类型char,signed char和unsigned char   称为字符类型。实现应定义char to   具有与签名相同的范围,表示和行为   char或unsigned char。

因此,当一个字符被赋值为整数时,是否设置了char的符号位是否存在歧义,因为它会影响分配了 plain char的整数的结果值。

我相信,本书中引用的文字引用了这一点,使用unsigned char明确地避免了这个问题。