C语言中的无符号字符数组字符串。

4

我有一个字符串数组,像这样

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”的表示方式,但我不确定如何处理。我想要一个字符串数组,其中每个字符串都是无符号字符而不是有符号字符的数组。能否有人帮忙解决?
注意:这是一个作业问题,但不是实际问题,只是可能解决方案中的一个小步骤。然而,如果您可以在不给出明确答案的情况下帮助我理解它,那将很好。谢谢。

5
简而言之,字符串文字是char*类型而不是unsigned char*类型。 - Mysticial
3
我强烈建议不要进行强制类型转换以避免破坏类型安全。 - Mysticial
在C和C++中没有按位相等性检查运算符。 - huseyin tugrul buyukisik
1
Mysticial 在字符串字面值是 const char* 上是正确的。我认为你试图做转换是出于错误的原因;你能描述一下你正在解决的更广泛的问题吗? - Sergey Kalinichenko
@dasblinkenlight 不,这是C语言,其中字符串字面值的类型为char[N],而不是const。(但尝试修改字符串字面值是未定义行为。) - Daniel Fischer
显示剩余2条评论
1个回答

4
C字符串是表示字符串的多种方式之一,由以null值结尾的char数组组成。当你的代码中有"0000"时,这就是你获得的类型。
你想要的是将"0000"赋值为一个以null值结尾的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风格字符串的大部分优势。使用无符号字符“string”,您无法使用标准字符串库,因此如果要使用printf或任何其他面向字符串的函数,则必须将其强制转换回有符号字符字符串类型。
实际上,对于每个可能的字符位置,您仅使用了两个值“0”和“1”。除非有充分的理由将其作为字符串进行处理,否则请考虑使用布尔值数组来降低“0hello”这样的字符串出现在代码中的几率,或者更好的方法是,如果您已经学习了位域(bit fields)的概念,可以使用无符号字符内的位域(bit fields)(摒弃了任何涉及字符串的概念)。
最后一种技术的优点包括使用更少的内存和该值不能是除0或1之外的任何值;但是,您将不得不编写一小组例程来将压缩的位(bit)转换为可读的内容。
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 ...

使用位域(bit-fields)的解决方案会是什么样子?如何将无符号字符(unsigned char)中的位作为位域来使用? - Willwsharp
@Willwsharp 位域只是被视为位的数字。要输入一个位字面常量,可以使用(警告,标准依赖/编译器依赖)0b00100101。这不会使“类型”成为位域,它仍然是无符号字符(因为C没有“位域”类型)。只有当位位置很重要且代码格式化突出显示项目时才有用。这就是为什么许多人在C中使用常量来指定标志8 == 0b1000 == CAN_READ,现在(flags&CAN_READ)可以与零进行比较(以确定是否设置了CAN READ标志)。 - Edwin Buck
嗯,这一切都有道理;我想我只是不明白它在上面的例子中如何使用。 - Willwsharp
@Willwsharp请将上面的char[]替换为unsigned char[] = { 0b00000000, 0b00000001, 0b00000010, 0b00000011, ...等等。0x07不是“十六进制类型”,而是“unsigned char”类型,其中位被指定为十六进制数字。通过执行0b00000111,它也不是“二进制类型”,而是“unsigned char”类型,其中位被指定为二进制数字。通过执行'a',它也不是“char类型”,而是一个“unsigned char”类型,其中位被指定为字符。类型附加到变量上。初始化数据仅提升到匹配类型。 - Edwin Buck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接