【问题标题】:char * vs unsigned char* what is the difference?char * 与 unsigned char* 有什么区别?
【发布时间】:2020-10-08 02:09:49
【问题描述】:

在带有 c 的 Linux 中,当我读/写二进制缓冲区时,我不明白 char*unsigned char* 之间的区别是什么?

当我不能使用char*而需要使用unsigned char*时?

【问题讨论】:

  • 无符号的不会有负数
  • 如果char 是有符号或无符号的,则定义它的实现。 unsigned char 始终未签名。
  • @Some 程序员老兄,我编辑了这篇文章,当我用 C 读取/写入二进制缓冲区时,我采取了
  • 例如,如果需要比较字节并认为0xff大于0x01,则应使用unsigned char *。但是如果你认为 0xff 小于 0x01,你应该使用signed char *

标签: c linux char unsigned


【解决方案1】:

第一次召回 C 有 unsigned charsigned charchar:3 种不同的类型。 charunsigned charsigned char 具有相同的范围。

[编辑]

OP 添加了“当我读/写二进制缓冲区时”,因此下面的部分(我的原始帖子)处理“char*unsigned char* 之间的区别”,并带有一个没有该 r/w 问题的示例案例.在本节中......

通过<stdio.h> 读取/写入二进制文件可以使用任何I/O 函数完成,尽管使用fread()/fwite() 更为常见。

对于面向字节的数据,所有 I/O 函数的行为都如同

字节输入函数从流中读取字符,就好像连续 调用fgetc 函数。 C17dr § 7.21.3 11
字节输出函数将字符写入流,就好像连续 调用fputc 函数。 § 7.21.3 12

让我们看看这两个。

...fgetc 函数将该字符作为unsigned char... § 7.21.7.1 2
fputc 函数写入 c 指定的字符(转换为 unsigned char)§ 7.21.7.3 2

因此,所有最低级别的 I/O 最好被认为是读/写unsigned char

现在直接解决

什么时候我不能使用char*而需要使用unsigned char*? (OP)

通过写入,char*unsigned char* 等指针可以在 OP 级代码中使用,而底层输出函数通过 unsigned char * 访问数据。这对 OP 的写入执行没有影响,除非 char 被编码为一个的补码/符号幅度 - 不会检测到陷阱代码。

与读取一样,底层输入函数通过unsigned char * 保存数据并且不会发生陷阱。通过int fgetc() 读取的单个字节将报告unsigned char 范围内的值,即使char签名

在读/写二进制缓冲区中使用unsigned char*char* 的重要性不在于I/O 调用本身(这都是unsigned char * 访问),而在于设置数据之前写作和阅读后数据的解释 - 请参阅下面的memcmp()



当我不能使用char*而需要使用unsigned char*时?

一个很好的例子是与字符串相关的代码。

虽然<string.h> 中的函数在函数参数中使用char*,但即使char签名,实现也好像charunsigned char

对于本子条款中的所有函数,每个字符都应被解释为具有unsigned char 类型(因此每个可能的对象表示都是有效的并且具有不同的值)。 C17dr § 7.24.1 3

因此,即使char 是一个签名 char,像int strcmp(char *a, char *b) 这样的函数的执行方式就像int strcmp(unsigned char *a, unsigned char *b)

  1. 当字符串的 有符号 char cchar d 具有不同符号的值时,这会有所不同。
    例如。假设c < 0, d > 0

    // 通过char * 访问,char 已签名 c unsigned 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);
}

[编辑]

同样适用于读取二进制数据并与memcmp()比较。

  1. 在不使用 2 补码的旧 C 实现中,可能有 2 个零:+0 和 -0(或陷阱)。

+0 在正确查看为unsigned char 时结束了一个字符串。 -0 不是终止字符串的 null 字符,即使作为 signed 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);
}

【讨论】:

  • 嗯?问:“我不明白其中的区别……”,答:“1)当……时,这会有所不同。”似乎几乎完全相关。
猜你喜欢
  • 2014-05-03
  • 2016-07-07
  • 1970-01-01
  • 2022-01-03
  • 2012-03-02
  • 1970-01-01
  • 2020-06-26
  • 1970-01-01
  • 2012-09-27
相关资源
最近更新 更多