char*与unsigned char*有什么区别?

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问题。在本节中 通过读取/写入二进制文

在使用c的Linux中,当我读/写二进制缓冲区时,我不明白
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 2
fputc
函数写入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
的实现也会像
was
unsigned 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 2
    fputc
    函数写入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);
    }