Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么C中的字符串函数在使用char而不是unsigned char的数组上工作?_C_String - Fatal编程技术网

为什么C中的字符串函数在使用char而不是unsigned char的数组上工作?

为什么C中的字符串函数在使用char而不是unsigned char的数组上工作?,c,string,C,String,在C标准库函数中,字符串的元素是chars。是否有一个很好的理由来决定它而不是无符号字符 对8位字符串使用无符号字符,有一些优点,尽管很小: 这更直观,因为我们通常将ASCII码存储为无符号值,并且在处理二进制数据时,我们更喜欢0x00到0xFF的无符号范围,而不是处理负数。所以我们必须投 使用无符号整数可能更快/更有效,或者在某些处理器上生成更小的代码 因为标准没有将字符定义为有符号字符,所以没有充分的理由。也没有任何好的理由说明char的符号性是由实现定义的。不存在任何类型的使用负数索引的

C
标准库函数中,字符串的元素是
char
s。是否有一个很好的理由来决定它而不是
无符号字符

对8位字符串使用
无符号字符
,有一些优点,尽管很小:

  • 这更直观,因为我们通常将ASCII码存储为无符号值,并且在处理二进制数据时,我们更喜欢0x00到0xFF的无符号范围,而不是处理负数。所以我们必须投
  • 使用无符号整数可能更快/更有效,或者在某些处理器上生成更小的代码

因为标准没有将字符定义为有符号字符,所以没有充分的理由。也没有任何好的理由说明char的符号性是由实现定义的。不存在任何类型的使用负数索引的符号表

我认为所有这些都源于一个错误的、奇怪的假设,即有8位整数,然后有“字符”,其中“字符”是某种神奇的神秘事物

这只是C标准中许多非理性缺陷之一,这些缺陷是从恐龙在地球上行走的时代继承下来的。char神秘的符号性并没有给语言带来任何变化,除了隐式整数提升可能导致与符号性相关的错误

编辑:

很可能他们让char被签名是因为他们希望它的行为与其他整数类型一样:short、int、long,标准保证这些类型在默认情况下都是有符号的

使用无符号整数可能更快/更有效,或者在某些处理器上生成更小的代码

你最终选择哪种类型并不完全是直观的。无论何时在表达式中使用char作为操作数,它都将被提升为int。类似地,常量字符文本“a”、“n”等的类型为int,而不是char。C语言强制编译器根据隐式提升规则(称为“整数提升”和“常用算术转换”/“平衡”)提升类型

一旦升级完成,编译器可能会将类型优化为最有效的类型,前提是它可以证明优化不会改变结果

如果您有此代码:

char a = 'a';
char b = 'b';
char c = a + b;
字里行间有许多模糊的事情。首先,文本“a”和“b”会被无声地从
int
截断为有符号/无符号字符。然后在表达式
a+b
中,a和b都被整数提升规则隐式提升为
int
类型。在两个
int
上执行加法。然后,结果会自动截断回有符号/无符号字符


如果编译器能够证明优化不会影响上述任何模糊性,那么它可能会用正常的8位操作来代替

好问题。由于该标准没有将
char
定义为无符号或有符号(这由实现决定),因此我猜想对
char
的偏好来自两个角度:

  • char
    unsigned char
    花费更少的时间进行键入,使得字符串操作函数的原型更易于阅读和使用
  • 因为最初的ASCII规范是7位的,所以为了C规范的缘故,有效值是否在0到127或0到255之间并不重要。8位字符集的标准化发生得晚得多

有三种相关类型:

  • 有符号字符
    ,用于存储小的有符号整数
  • 无符号字符
    ,用于存储小的无符号整数
  • char
    ,用于存储字符
我想你真正想知道的是为什么
char
不是无符号类型

曾经有一段时间[1]
char
被描述为已签名(见第4页),但即使在当时,“符号传播功能在其他实现中消失”,因此它的行为已经表现为在某些地方已签名,在其他地方未签名。我认为实现的选择仅仅反映了对他们来说最简单的方式(例如,在PDP-11上,第一个C实现是针对它的,
MOVB
做了符号扩展,我不记得有一种方法可以将字节移动到一个字而不获得符号扩展)

现在,我知道的大多数实现都使用带符号的
char
。我所知道的唯一一个无符号的
char
是来自IBM的,是EBCDIC委托it的支持(基本字符集中字符的字符代码必须是正数,EBCDIC的大多数字符代码都在128以上)


[1] 字符的签名是由实现定义的

对于您所描述的问题,一个更干净的解决方案是强制要求纯
char
必须无符号

普通
char
可能有符号或无符号的原因部分是历史原因,部分与性能有关


C的早期版本没有无符号类型。由于ASCII仅涵盖0到127的范围,因此假定将
char
设为有符号类型没有特别的缺点。一旦做出了这个决定,一些程序员可能已经编写了依赖于此的代码,后来的编译器将
char
保留为有符号类型,以避免破坏这样的代码

引用1975年《K&R1》出版前3年的a:

字符(声明的,以下称为,
char
)从 ASCII集;它们占据8位中最右边的7位 字节。也可以将
char
s解释为带符号的2的补码 8位数字

EBCDIC需要8位无符号
字符
,但显然基于EBCDIC的机器
char ch = '0';
ch ++;