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

标签 c linux char unsigned

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

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

最佳答案

首先记忆C有unsigned char , signed charchar : 3种不同的类型。 charunsigned char 具有相同的范围或 signed char .

[编辑]

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

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

对于面向字节的数据,所有 I/O 函数的行为就好像

The byte input functions read characters from the stream as if by successive calls to the fgetc function. C17dr § 7.21.3 11
The byte output functions write characters to the stream as if by successive calls to the fputc function. § 7.21.3 12

那么让我们看看这两个。

... the fgetc function obtains that character as an unsigned char ... § 7.21.7.1 2
The fputc function writes the character specified by c (converted to an unsigned char) § 7.21.7.3 2

因此,最好将最低级别的所有 I/O 视为读/写 unsigned char .

现在直接地址

When I must not using char* and need to use unsigned char*? (OP)

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

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

使用 unsigned char* 的重要性与 char*在读/写二进制缓冲区中,与其说是 I/O 调用本身(所有 unsigned char * 访问),不如说是在写入前设置数据和读取后解释数据 - 参见 memcmp()下面。



When I must not using char* and need to use unsigned char*?

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

尽管在 <string.h> 中起作用使用 char*在函数参数中,实现就像 char 一样执行是unsigned char ,即使 char签名

For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char (and therefore every possible object representation is valid and has a different value). 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 < d 为真 //通过 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 不是终止字符串的空字符,即使是已签名 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);
}

关于char * vs unsigned char* 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62442859/

相关文章:

linux - 为什么在 Linux 上打包的 AIR 应用程序在 Mac 上使用时会损坏?

C 静态字符数组与动态字符数组的奇怪行为

c - VxWorks串口读取字符串转换乱码

C线程打印数字序列: with even and odd number printing threads running parallely

c - 优化后的反汇编代码局部变量保存在哪里

linux - 在 Ubuntu 13.10 上构建 wifi 驱动程序时出错

c - 如何创建仅指向字符串第一个字母的指针

c - 在 C 编程中,for(int i=0; st[i]; i++) 和 for(int i=0; i<st[length of the array];i++) 有什么区别

c++ - Linux API 列出正在运行的进程?

linux - 如何显示用户输入的最长行