char*与unsigned char*有什么区别?
在使用c的Linux中,当我读/写二进制缓冲区时,我不明白char*与unsigned char*有什么区别?,c,linux,char,unsigned,C,Linux,Char,Unsigned,在使用c的Linux中,当我读/写二进制缓冲区时,我不明白char*和unsigned char*之间的区别是什么 当我不能使用字符*并且需要使用无符号字符*?第一次调用C时,有无符号字符,有符号字符和字符:3种不同的类型char与unsigned char或signed char具有相同的范围 [编辑] OP添加了“当我读/写二进制缓冲区时”,因此下面的部分(我的原始帖子)讨论了“无符号字符*和无符号字符*之间的区别”,并给出了一个示例案例,而不涉及r/w问题。在本节中 通过读取/写入二进制文
char*
和unsigned char*
之间的区别是什么
当我不能使用
字符*
并且需要使用无符号字符*
?第一次调用C时,有无符号字符
,有符号字符
和字符
:3种不同的类型char
与unsigned char
或signed char
具有相同的范围
[编辑]
OP添加了“当我读/写二进制缓冲区时”,因此下面的部分(我的原始帖子)讨论了“无符号字符*和无符号字符*
之间的区别”,并给出了一个示例案例,而不涉及r/w问题。在本节中
通过
读取/写入二进制文件可以通过任何I/O函数完成,尽管使用fread()/fwite()
更常见
对于面向字节的数据,所有I/O函数的行为就像
字节输入函数从流中读取字符,就像通过连续
调用fgetc
函数。C17dr§7.21.3 11字节输出函数将字符写入流,就像通过连续 调用
fputc
函数。§7.21.3 12
让我们看看这两个
。。。fgetc
函数将该字符作为无符号字符
获取。。。§7.21.7.1 2fputc
函数写入c指定的字符(转换为无符号字符
)§7.21.7.3 2
因此,最低级别的所有I/O最好被认为是读/写无符号字符
现在直接解决
当我不能使用char*
并且需要使用无符号char*
时?(OP)
通过写入,诸如char*
、unsigned char*
或其他指针可以在操作级代码中使用,但底层输出函数通过unsigned char*
访问数据。这对OP的写操作没有影响,除非char
被编码为一个的补码/符号大小-陷阱码不会被检测到
与读取类似,底层输入函数通过unsigned char*
保存数据,不会出现陷阱。通过int fgetc()
读取的单个字节将报告无符号字符
范围内的值,即使字符
有符号
在读/写二进制缓冲区中使用unsigned char*
与char*
的重要性不在于I/O调用本身(它都是unsigned char*
access),而在于写入前的数据设置和读取后的数据解释-请参阅下文memcmp()
当我不能使用
char*
并且需要使用无符号char*
时
与字符串相关的代码就是一个很好的例子
尽管
中的函数在函数参数中使用char*
,但即使在char
已签名的情况下,char
的实现也会像wasunsigned char
一样执行
对于本子条款中的所有函数,应将每个字符解释为具有类型无符号字符
(因此,每个可能的对象表示都是有效的,并且具有不同的值)。C17dr§7.24.1 3
因此,即使char
是一个有符号的char
,像int-strcmp(char*a,char*b)
这样的函数执行起来就像int-strcmp(unsigned char*a,unsigned char*b)
当字符串由带符号的char c
和带有不同符号值的char d
区分时,这会产生差异。
例如,假设c<0,d>0
//通过char*
访问,并且char
已签名
cunsigned char*
c>d为假
这会导致与strcmp()返回的符号不同,因此会影响排序字符串
// Incorrect code when `char` is signed.
int strcmp(const char *a, const char *b) {
while (*a == *b && *a) { a++; b++; }
return (*a > *b) - (*a < *b);
}
// Correct code when `char` is signed or unsigned, 2's complement or not
int strcmp(const char *a, const char *b) {
const char *ua = a;
const char *ub = b;
while (*ua == *ub && *ua) { ua++; ub++; }
return (*ua > *ub) - (*ua < *ub);
}
第一次调用C有
无符号字符
,有符号字符
和字符
:3种不同的类型char
与unsigned char
或signed char
具有相同的范围
[编辑]
OP添加了“当我读/写二进制缓冲区时”,因此下面的部分(我的原始帖子)讨论了“无符号字符*和无符号字符*
之间的区别”,并给出了一个示例案例,而不涉及r/w问题。在本节中
通过
读取/写入二进制文件可以通过任何I/O函数完成,尽管使用fread()/fwite()
更常见
对于面向字节的数据,所有I/O函数的行为就像
字节输入函数从流中读取字符,就像通过连续
调用fgetc
函数。C17dr§7.21.3 11字节输出函数将字符写入流,就像通过连续 调用
fputc
函数。§7.21.3 12
让我们看看这两个
。。。fgetc
函数将该字符作为无符号字符
获取。。。§7.21.7.1 2fputc
函数写入c指定的字符(转换为无符号字符
)§7.21.7.3 2
因此,最低级别的所有I/O最好被认为是读/写无符号字符
现在直接解决
当我不能使用char*
并且需要使用无符号char*
时?(OP)
通过写入,诸如char*
、unsigned char*
或其他指针可以在操作级代码中使用,但底层输出函数通过unsigned char*
访问数据。这对OP的写操作没有影响,除非char
被编码为一个的补码/符号大小-陷阱码不会被检测到
同样地,在阅读方面,这一点也很重要
// Incorrect code when `char` is signed and not 2's complement.
// Conversion to `unsigned char` done too late.
int strcmp(const char *a, const char *b) {
while ((unsigned char)*a == (unsigned char)*b && (unsigned char)*a) { a++; b++; }
return ((unsigned char)*a > (unsigned char)*b) - ((unsigned char)*a < (unsigned char)*b);
}