【问题标题】:C unsigned char array of stringsC unsigned char 字符串数组
【发布时间】:2012-09-15 12:11:07
【问题描述】:

我有一个这样的字符串数组

char *T[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};

但是,当我这样做时,每个字符串都是一个无符号字符数组

unsigned char *T[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};

我收到错误消息“使用 'char[5]' 类型的表达式初始化 'unsigned char *' 在指向具有不同符号的整数类型的指针之间转换。”我猜这意味着正在使用的“0”和“1”的一些表示已签名,但我不确定为什么/如何处理它。我想要一个字符串数组,其中每个字符串都是一个无符号字符数组,而不是有符号字符数组。有人可以帮忙吗?

注意:这是针对硬件问题,但不是实际问题,只是众多可能解决方案之一中的一小步。但是,如果您能在不给我明确答案的情况下帮助我理解它,那就太好了。谢谢。

【问题讨论】:

  • 简单地说,字符串字面量的类型是char*而不是unsigned char*
  • @tuğrulbüyükışık 我强烈建议不要使用强制转换来破坏类型安全。
  • 那么 char + unsigned char 的联合数组效果很好,因为每个都是 1 字节,所以字节序不会成为问题。别名?
  • 是否需要使字符无符号?你会和他们进行什么样的比较?
  • Mysticial 在字符串文字为const char* 上是正确的。我认为您出于错误的原因尝试进行转换;你能描述一下你正在解决的更广泛的问题吗?

标签: c arrays string


【解决方案1】:

C 字符串是表示字符串的多种方式之一,它由 char 的数组组成,以 char 结尾,其值为 null。当你的代码中有“0000”时,这就是你得到的类型。

您想要将“0000”分配为unsigned char 的数组,该数组由具有空值的尾随unsigned char 终止。考虑到您从什么开始,您将不得不进行转换,或者可能以不需要转换的方式表示您的初始数据。

unsigned char T[][] = { { 0x30, 0x30, 0x30, 0x30, 0x00 }, 
               { 0x30, 0x30, 0x30, 0x31, 0x00 }, 
               { 0x30, 0x30, 0x31, 0x30, 0x00 }, 
               { 0x30, 0x30, 0x31, 0x31, 0x00 }, 
               { 0x30, 0x31, 0x30, 0x30, 0x00 }, 
               { 0x30, 0x31, 0x30, 0x31, 0x00 }, 
               { 0x30, 0x31, 0x31, 0x30, 0x00 }, 
               { 0x30, 0x31, 0x31, 0x31, 0x00 }, 
               { 0x31, 0x30, 0x30, 0x30, 0x00 }, 
               { 0x31, 0x30, 0x30, 0x31, 0x00 }, 
               { 0x31, 0x30, 0x31, 0x30, 0x00 }, 
               { 0x31, 0x30, 0x31, 0x31, 0x00 }, 
               { 0x31, 0x31, 0x30, 0x30, 0x00 }, 
               { 0x31, 0x31, 0x30, 0x31, 0x00 }, 
               { 0x31, 0x31, 0x31, 0x30, 0x00 }, 
               { 0x31, 0x31, 0x31, 0x31, 0x00 }
              };

我看到这种方法的主要问题是它首先消除了拥有 C 样式字符串的大部分优势。使用无符号字符“字符串”,您没有任何标准字符串库可供您使用,因此如果您想使用 printf 或任何其他面向字符串的函数,则必须转换回有符号字符字符串类型。

实际上,您只为每个可能的字符位置“0”和“1”使用了两个值。除非有令人信服的理由在字符串中执行此操作,否则请考虑使用布尔值数组来减少像“0hello”这样的字符串进入代码的机会,或者如果你有 更好被引入位域,使用 unsigned char 中的位作为位域(丢弃您处理字符串的任何概念)。

最后一种技术的优点包括使用较少的内存,并且值不能为 0 或 1 以外的值;但是,您必须编写一小部分例程来将打包的位转换为人类可读的内容。

unsigned char[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
                    0x05, 0x06, 0x07, 0x08, 0x09,
                    0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
                    0x0F };

void displayChar(unsigned char value) {
  switch (value) {
    case 0x00: printf("0000"); break;
    case 0x01: printf("0001"); break;
    case 0x02: printf("0010"); break;
    case 0x03: printf("0011"); break;
... and so on ...

【讨论】:

  • 使用位域的解决方案会是什么样子?如何将 unsigned char 中的位用作位域?
  • @Willwsharp 位字段只是被视为位的数字。要键入一个位字面常量,可以使用(警告,标准相关/编译器相关)0b00100101 它不会使“类型”成为位字段,它仍然是一个无符号字符(因为 C 没有“位字段”类型。仅当位位置很重要并且代码格式使其突出显示项目时才有用。这就是为什么这么多人在 C 中使用常量来指定标志 8 == 0b1000 == CAN_READ 和现在 ( flags & CAN_READ) 可以比较为零(以确定是否设置了 CAN READ 标志)
  • 嗯,这一切都说得通;我想我只是想念在上面的例子中如何使用它
  • @Willwsharp 将上面的 char[] 替换为 unsigned char[] = { 0b00000000, 0b00000001, 0b00000010, 0b00000011, ... 等等。 0x07 不是“十六进制类型”,它是“无符号字符”类型,其中位指定为十六进制数字。通过执行 0b00000111,它又不是“二进制类型”,而是“无符号字符”类型,其中位被指定为二进制数。通过执行“a”,它再次不是“char 类型”,而是“unsigned char”类型,其中位被指定为字符。它们的类型附加到变量。初始化数据仅提升为匹配类型。
猜你喜欢
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2011-04-19
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多