Answers:
在C ++中,存在三种不同的字符类型:
char
signed char
unsigned char
如果将字符类型用于文本,请使用不限定的字符char
:
'a'
或的类型'0'
。"abcde"
它也可以作为数字值计算,但是不确定该值是带符号的还是无符号的。注意通过不等号进行字符比较-尽管如果将自己限制为ASCII(0-127),则几乎是安全的。
如果将字符类型用作数字,请使用:
signed char
,该范围至少为-127至127。(-128至127是常见的)unsigned char
,该值至少为0到255。“至少”,因为C ++标准仅给出了每种数字类型都必须覆盖的最小范围的值。sizeof (char)
要求1为1(即一个字节),但是理论上一个字节可以是例如32位。sizeof
仍将其大小报告为1
-表示您可以拥有sizeof (char) == sizeof (long) == 1
。
sizeof
因为它不是函数,而是运算符。取变量的大小时,省略括号是一种更好的样式。sizeof *p
或sizeof (int)
。这样可以快速弄清楚是否适用于类型或变量。同样,在后面加上括号也是多余的return
。这不是功能。
char
:这是字符文字的类型,例如'a'
或'0'
。” 在C ++中是正确的,但在C中不是。在C中,'a'
是int
。
这取决于实现,因为C标准没有定义的符号char
。根据平台的不同,char可能是signed
或unsigned
,因此您需要明确要求signed char
或unsigned char
您的实现是否依赖于它。仅char
在您打算表示字符串中的字符时使用,因为这将与您的平台在字符串中放置的字符匹配。
signed char
和之间的区别unsigned char
是您所期望的。在大多数平台上,signed char
将是8位二进制补码,范围是从-128
到127
,并且unsigned char
将是8位无符号整数(0
to 255
)。注意,该标准不要求char
类型具有8位,仅要求sizeof(char)
return 1
。您可以在位的数量得到一个字符用CHAR_BIT
的limits.h
。如今,几乎没有任何平台会提供8
,而不是。
有这个问题的一个很好的总结在这里。
正如我自发布此文章以来其他人提到的那样int8_t
,uint8_t
如果您真的想表示小整数,最好使用。
CHAR_BIT
标准要求至少为8位。
因为我觉得确实需要这样做,所以我只想陈述一些C和C ++的规则(在这方面它们是相同的)。首先,所有unsigned char
参与的位都参与确定该值(如果有任何未签名的char对象)。第二,unsigned char
明确声明未签名。
现在,我与某人讨论了将-1
int类型的值转换为时会发生什么unsigned char
。他拒绝将结果的unsigned char
所有位都设置为1 的想法,因为他担心符号的表示。但他不必。遵循此规则,转换立即达到了预期的目的:
如果新类型是无符号的,则通过重复添加或减去比新类型中可以表示的最大值多一个值来转换该值,直到该值在新类型的范围内为止。(
6.3.1.3p2
在C99草案中)
那是数学上的描述。C ++用模演算来描述它,这产生了相同的规则。无论如何,不能保证整数-1
中的所有位在转换前都是1。那么,我们有什么,可以断言结果的unsigned char
所有CHAR_BIT
位都变为1?
UCHAR_MAX+1
,以-1
将产生在范围内的值,即UCHAR_MAX
够了,实际上!因此,每当您想拥有一个unsigned char
全部的位时,您就会
unsigned char c = (unsigned char)-1;
随之而来的是,转换不只是截断高阶位。二进制补码的幸运事件是它只是一个截断,但对于其他符号表示形式并不一定是正确的。
UCHAR_MAX
?
(unsigned type)-1
是某种成语。~0
不是。
int x = 1234
和char *y = &x
。1234
is的二进制表示形式00000000 00000000 00000100 11010010
。我的机器是小字节序的,因此它将其反转并存储在内存中11010010 00000100 00000000 00000000
LSB优先。现在主要部分。如果我使用printf("%d" , *p)
。printf
将读取第一个字节11010010
只输出-46
,但11010010
就是210
为何还打印-46
。我真的很困惑,我想一些将char转换为整数的促销正在做某事,但我不知道。
例如unsigned char的用法:
unsigned char
通常在计算机图形学中使用,它经常(尽管并非总是)为每个颜色分量分配一个字节。通常会看到以24(或32)位表示的RGB(或RGBA)颜色,每个为unsigned char
。由于unsigned char
值在[0,255]范围内,因此通常将这些值解释为:
因此,最终将得到RGB红色为(255,0,0)->(100%红色,0%绿色,0%蓝色)。
为什么不使用signed char
?算术和位移会成为问题。正如已经说明的,signed char
的范围实际上偏移了-128。将RGB转换为灰度的一种非常简单且幼稚的方法(几乎未使用)是对所有三个颜色分量求平均值,但是当颜色分量的值为负时,就会遇到问题。使用unsigned char
算术运算时,红色(255,0,0)平均为(85,85,85)。但是,如果值是signed char
s(127,-128,-128),我们最终将得到(-99,-99,-99),在我们的unsigned char
空间中将是(29,29,29),这是不正确的。
如果要将字符用作小整数,最安全的方法是使用int8_t
and uint8_t
类型。
int8_t
并且uint8_t
是可选的,并且未在字节大小不完全为8位的体系结构上定义。相反,signed char
并且unsigned char
始终可用,并保证至少持有8位。这可能是常见的方法,但不是最安全的方法。
signed char
和unsigned char
?还是在特定情况下您会推荐一个更好的“更安全”的选择?例如,坚持使用“实数”整数类型signed int
,unsigned int
而出于某种原因呢?
signed char
和unsigned char
可移植到所有符合要求的实现中,将节省存储空间,但可能会导致代码大小增加。在某些情况下,通过将较小的值存储在规则整数类型的位字段或单个位中,可以节省更多的存储空间。这个问题没有绝对的答案,这种方法的针对性取决于具体情况。而且这个答案也不能解决这个问题。
char
并unsigned char
不能保证在所有平台上均为8位类型,而是保证为8位或更大。某些平台具有9位,32位或64位byte。但是,当今最常见的平台(Windows,Mac,Linux x86等)具有8位字节。
An unsigned char
是无符号字节值(0到255)。您可能会想到char
成为“字符”,但这实际上是一个数字值。常规char
符号是带符号的,因此您有128个值,并且这些值使用ASCII编码映射到字符。但是无论哪种情况,您存储在内存中的都是一个字节值。
就直接值而言,当已知值介于CHAR_MIN
或之间时使用常规字符CHAR_MAX
,而无符号字符在正数端提供两倍的范围。例如,如果CHAR_BIT
为8,则常规的范围char
仅保证为[0,127](因为它可以签名或无符号),而unsigned char
将为[0,255],并且signed char
为[-127,127]。
就其用途而言,标准允许将POD(普通旧数据)的对象直接转换为无符号字符数组。这使您可以检查对象的表示形式和位模式。对于char或signed char,不存在相同的安全类型修剪保证。
unsigned char
,而不是一个阵列具体地,&任何“转化率”是只由正式定义复制从对象到一个真实的,宣告阵列的unsigned char
&然后检查后者。尚不清楚OR是否可以直接重新解释为这样的数组,是否需要使用指针算术,即==
在此用法中是否使用“序列” “数组”。有一个核心问题#1701已公开,希望对此予以澄清。值得庆幸的是,这种模糊性最近确实困扰了我。
unsigned char
OR 的第一个,然后++ptr
从那里开始使用它来读取它的每个字节是合理的……但是AFAICT,没有明确定义为允许,所以我们可以从标准中的许多其他段落(以及在许多方面,仅仅是的存在memcpy
)推断出它“可能还可以”,类似于拼图游戏。这是不理想的。好吧,也许措辞最终会有所改善。这是我提到的CWG问题,但缺乏链接空间-open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1701
unsigned char
是所有骗术的心脏。在几乎所有平台的ALL编译器中,unsigned char
a只是一个字节和(通常)8位的无符号整数,可以将其视为小整数或一包位。
正如其他人所说,在成瘾中,标准没有定义字符的符号。所以你有3种不同的char
类型:char
,signed char
,unsigned char
。
无符号字符使用保留给常规字符符号的位作为另一个数字。这会将范围更改为[0-255],而不是[-128-127]。
通常,当您不想要符号时使用未签名的字符。这在执行诸如移位位(shift扩展符号)之类的操作以及将char作为字节而不是将其用作数字的其他操作时会有所不同。
signed char
和unsigned char
都代表1字节,但是它们具有不同的范围。
Type | range
-------------------------------
signed char | -128 to +127
unsigned char | 0 to 255
在signed char
如果我们考虑char letter = 'A'
,“A”是代表在65二进制ASCII/Unicode
,如果65可以存储,还-65可以存储。那里没有负的二进制值,ASCII/Unicode
无需担心负值。
例
#include <stdio.h>
int main()
{
signed char char1 = 255;
signed char char2 = -128;
unsigned char char3 = 255;
unsigned char char4 = -128;
printf("Signed char(255) : %d\n",char1);
printf("Unsigned char(255) : %d\n",char3);
printf("\nSigned char(-128) : %d\n",char2);
printf("Unsigned char(-128) : %d\n",char4);
return 0;
}
输出-
Signed char(255) : -1
Unsigned char(255) : 255
Signed char(-128) : -128
Unsigned char(-128) : 128