鉴于有符号和无符号整数使用相同的寄存器等,并且只是以不同的方式解释位模式,并且 C 字符基本上只是 8 位整数,那么 C 中的有符号和无符号字符之间有什么区别?我知道 char 的符号是实现定义的,我根本无法理解它如何产生影响,至少当 char 用于保存字符串而不是做数学时。

有帮助吗?

解决方案

它不会让字符串的差。但在C你可以使用一个char做数学的时候,就会有所作为。

在实际上,在受限的存储器环境中工作时,如嵌入式8个应用一个char将经常被用来做数学,然后它使一个很大的区别。这是因为存在由默认C中没有byte类型。

其他提示

就它们代表的价值观而言:

无符号字符:

  • 跨越取值范围 0..255 (00000000..11111111)
  • 值在低边缘周围溢出,如下所示:

    0 - 1 = 255 (00000000 - 00000001 = 11111111)

  • 值在高边沿溢出,如下所示:

    255 + 1 = 0 (11111111 + 00000001 = 00000000)

  • 按位右移运算符 (>>) 进行逻辑移位:

    10000000 >> 1 = 01000000 (128 / 2 = 64)

签名字符:

  • 跨越取值范围 -128..127 (10000000..01111111)
  • 值在低边缘周围溢出,如下所示:

    -128 - 1 = 127 (10000000 - 00000001 = 01111111)

  • 值在高边沿溢出,如下所示:

    127 + 1 = -128 (01111111 + 00000001 = 10000000)

  • 按位右移运算符 (>>) 进行算术移位:

    10000000 >> 1 = 11000000 (-128 / 2 = -64)

我包含了二进制表示形式,以表明值包装行为是纯粹的、一致的二进制算术,并且与有符号/无符号的 char 无关(右移除外)。

更新

评论中提到的一些特定于实现的行为:

#include <stdio.h>

int main(int argc, char** argv)
{
    char a = 'A';
    char b = 0xFF;
    signed char sa = 'A';
    signed char sb = 0xFF;
    unsigned char ua = 'A';
    unsigned char ub = 0xFF;
    printf("a > b: %s\n", a > b ? "true" : "false");
    printf("sa > sb: %s\n", sa > sb ? "true" : "false");
    printf("ua > ub: %s\n", ua > ub ? "true" : "false");
    return 0;
}


[root]# ./a.out
a > b: true
sa > sb: true
ua > ub: false

有字符串进行排序时是很重要的。

有几个差别。最重要的是,如果通过分配一个过大或小的整数溢出字符的有效范围和char签订后,所得到的值是实现定义的,甚至一些信号(C语言)可以提高,为所有符号类型。对比一下,当你分配的东西过大或小,unsigned char类型的情况:值环绕,你会得到精确定义的语义。例如,分配-1到一个无符号的字符,你会得到一个UCHAR_MAX。所以,只要你有一个字节作为一个从0到2 ^ CHAR_BIT,你应该使用无符号的字符来存放它。

标识也有差别传递到可变参数的功能时:

char c = getSomeCharacter(); // returns 0..255
printf("%d\n", c);

假设分配到c。将过大的char来表示的值,该机采用二进制补码。许多实施的行为为您分配一个太大价值的焦炭,在该位格局不会改变的情况下。如果int将能够表示(它是大多数实现方式)炭的所有值,则炭被提升经过对printf之前为int。那么,什么是传递的值是负的。促进为int将保留那个标志。所以,你会得到一个负的结果。然而,如果char是无符号的,则该值是无符号的,并促进为int将产生一个正int值。你可以使用无符号的字符,同时为变量赋值,并通过对printf则打印出一些积极的事情,那么你将得到精确定义的行为。

请注意,一个字符,无符号和有符号的字符都是至少 8个位宽。没有要求,即炭准确 8个位宽。然而,对于大多数系统这是事实,但对有些人,你会发现它们使用32位字符。在C和C ++一个字节被定义为具有炭的大小,所以在C字节也并不总是精确的8位。

另一个不同之处是,在C,一个无符号字符必须没有填充比特。也就是说,如果你发现CHAR_BIT是8,那么unsigned char类型的值必须介于0。2 ^ CHAR_BIT-1。这同样适用于字符,如果是无符号。对于符号的字符,你不能假设有关值的范围任何东西,即使你知道你的编译器是如何实现的标志的东西(二进制补码或其他选项),也有可能在其未使用的填充位。在C ++中,存在用于所有三个字符类型没有填充比特。

  
    

“是什么意思了签署一个char?”

  

传统上,ASCII字符集包括7位的字符编码。 (相对于8位EBCIDIC。)

当C语言设计并实现,这是一个问题显著。 (由于各种原因像通过串行调制解调器设备的数据传输。)额外的位具有使用了如奇偶校验。

A“符号字符”恰好是完美的这种表示。

二进制数据,OTOH,是简单地把数据的每个8位“块”的值,因此需要没有任何迹象。

字节算术对于计算机图形学非常重要(其中 8 位值通常用于存储颜色)。除此之外,我可以想到 char 符号很重要的两种主要情况:

  • 转换为更大的 int
  • 比较功能

令人讨厌的是,如果您的所有字符串数据都是 7 位,那么这些不会对您造成影响。然而,如果您试图使您的 C/C++ 程序变得 8 位干净,它可能会成为一个无休无止的隐晦错误来源。

符号性作品在chars几乎相同的方式,因为它在其他整型呢。正如您所指出的,字符是真的只是一个字节的整数。 (不一定8位的,但有一个区别;!字节可能比8位大在某些平台上,并chars都相当依赖于字节由于charsizeof(char)定义中的CHAR_BIT宏,在<limits.h>或C ++的<climits>定义,将告诉你有多少位都在char)。

至于为什么你要带符号的字符:C和C ++,不存在所谓的byte标准型。编译器,chars是字节,反之亦然,并且它不区分它们。然而,有时候,你想 - 有时你的的是char是一个字节数,在这些情况下(一个字节可以特别一系列多么小都有),你也通常是不管数量签订与否。我个人使用的符号性(或unsignedness)说,一定char是(数字)“字节”,而不是一个角色,那它将会被数字使用。没有指定的符号性,即char真的是一个字符,并且旨在被用作文本。

我用来做,与其。现在,C和C的新版本++有(u?)int_least8_t(目前在<stdint.h><cstdint> typedef定义),这是更明确的数字(尽管他们通常会只是符号和无符号char类型的类型定义是这样)。

如果你选择做数学字符唯一的情况我能想象这是一个问题。这是完全合法的编写以下代码。

char a = (char)42;
char b = (char)120;
char c = a + b;

根据炭的符号性,C可能是两个值之一。如果字符的是无符号,则C会(焦炭)162。如果他们签名,则它会溢出的情况下,作为一个符号字符的最大值为128。我猜大多数实现将只返回(焦炭)-32。

关于签署字符的一件事是,你可以测试C> =“”(空格),并确认这是一个正常的可打印的ASCII字符。当然,这不是便携式的,所以不是非常有用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top