代码之家  ›  专栏  ›  技术社区  ›  drigoSkalWalker

关于编码有符号/无符号的Char C问题

  •  10
  • drigoSkalWalker  · 技术社区  · 16 年前

    我读到C没有定义char是有符号的还是无符号的,在GCC页面中,这说明它可以在x86上有符号,在PowerPPC和ARM中是无符号的。

    好的,我正在用GLIB编写一个程序,将char定义为gchar(不超过它,只是一种标准化的方法)。

    我的问题是,UTF-8怎么样?它使用的不仅仅是一块内存?

    假设我有一个变量

    unsigned char*string=“带UTF8编码的我的字符串~>ÃÔ;

    如果我把变量声明为

    我将只有127个值(所以我的程序将存储更多的内存块)或者UTF-8也将变为负数?

    对不起,如果我不能正确解释,但我觉得我有点复杂。

    注: 谢谢你的回答

    我不明白它是如何正常解释的。

    我认为,就像ascii一样,如果我的程序中有一个有符号和无符号的字符,字符串有不同的值,这会导致混淆,想象一下utf8中的情况。

    8 回复  |  直到 16 年前
        1
  •  6
  •   user694733    8 年前

    我有几次请求解释我的评论。

    事实上 char 类型可以默认为有符号或无符号类型,当您比较字符并期望某种顺序时,该类型可以是有意义的。特别是,UTF8使用高位(假设 烧焦 是一种8位类型,这在绝大多数平台中都是正确的),用于指示字符代码点需要表示多个字节。

    一个快速而肮脏的问题示例:

    #include <stdio.h>
    int main( void)
    {
        signed char flag = 0xf0;
        unsigned char uflag = 0xf0;
    
        if (flag < (signed char) 'z') {
            printf( "flag is smaller than 'z'\n");
        }
        else {
            printf( "flag is larger than 'z'\n");
        }    
    
    
        if (uflag < (unsigned char) 'z') {
            printf( "uflag is smaller than 'z'\n");
        }
        else {
            printf( "uflag is larger than 'z'\n");
        }
        return 0;
    }
    

    在我工作的大多数项目中 烧焦 类型通常是避免的,我们使用typedef显式地指定 unsigned char . 类似于 uint8_t stdint.h

    typedef unsigned char u8;
    

    一般处理 无符号字符 类型似乎工作得很好,几乎没有问题——我偶尔看到的一个问题是,当使用这种类型的东西来控制循环时:

    while (uchar_var-- >= 0) {
        // infinite loop...
    }
    
        2
  •  5
  •   Tronic    16 年前

    使用无符号字符有其优点和缺点。最大的好处是,您不会得到符号扩展或其他有趣的功能,如符号溢出,将产生意想不到的计算结果。无符号字符还与<cctype>宏/函数(如isalpha(ch))兼容(所有这些都需要无符号字符范围内的值)。另一方面,所有I/O函数都需要char*,这要求您在执行I/O时进行强制转换。

    至于UTF-8,将其存储在有符号或无符号数组中是可以的,但是必须小心使用那些字符串,因为它们不能保证是有效的UTF-8。C++0x添加UTF-8字符串文字,以避免可能出现的问题,我希望下一个C标准也采用这些。

    不过,一般来说,只要确保源代码文件始终是UTF-8编码的,就应该没问题。

        3
  •  4
  •   Ben Zotto sberry    16 年前

    两件事:

    1. char类型是有符号的还是无符号的不会影响您将UTF8编码的字符串转换为您正在使用的任何显示字符串类型(WCHAR或whatnot)的能力。不用担心,换句话说:UTF8字节只是字节,无论你用什么作为编码器/解码器都会做正确的事情。

    2. 你的困惑可能是你想这么做:

      unsigned char *string = "This is a UTF8 string";
      

      不要这样做--你在混合不同的概念。UTF-8编码的字符串只是一个字节序列。C字符串文字(如上所述)并不是真正用来表示这个的;它们是用来表示“ASCII编码”字符串的。尽管在某些情况下(像我这里的情况),它们最终是相同的,在你的例子中,它们可能不是。当然在其他情况下也不会。从外部资源加载Unicode字符串。一般来说,我会小心在.c源文件中嵌入非ASCII字符;即使编译器知道如何处理它们,工具链中的其他软件也可能不知道。

        4
  •  2
  •   Andrey    16 年前

    有符号/无符号只影响算术运算。如果char是无符号的,那么更高的值将是正值。如果签了字,它们将是否定的。但范围还是一样的。

        5
  •  1
  •   Daren Thomas    16 年前

    不是真的, unsigned / signed 不指定一个变量可以容纳多少个值。它指明了它们是如何 解释 .

    所以,一个 unsigned char 具有与 signed char ,除了一个有负数而另一个没有。它仍然是8位(如果我们假设 char 有8个位子,我不确定它在哪里都有)。

        6
  •  1
  •   Graphics Noob    16 年前

    使用char*作为字符串没有区别。唯一有符号/无符号的时间会产生影响的是,您是将其解释为一个数字,比如算术,还是将其打印为一个整数。

        7
  •  0
  •   spoulson    16 年前

    UTF-8 不能假定字符存储在一个字节中。UTF-8字符可以是1-4字节宽。所以,a char , wchar_t , signed unsigned 不足以假设一个单元总是可以存储一个UTF-8字符。

    大多数平台(如PHP、.NET等)通常都会构建字符串(如 char[] 在C)中,使用库在编码和解析字符串中的字符之间进行转换。

        8
  •  0
  •   brat    8 年前

    关于你的问题:

    如果我有一个单字符或无符号的字符数组,会不会让我的程序运行错误?德里戈斯卡沃克

    对。是我的。下面是我的应用程序中一个简单的可运行的摘录,如果使用普通的签名字符,那么这个摘录就完全错了。 在将所有字符更改为无符号参数后尝试运行它。这样地:

    int有效( 未签名 字符c);

    然后它应该能正常工作。

    #include <stdio.h>
    
    int is_valid(char c);
    
    int main() {
    
        char ch = 0xFE;
        int ans = is_valid(ch);
        printf("%d", ans);
    
    }
    
    int is_valid(char c) {
        if((c == 0xFF) || (c == 0xFE)) {
        printf("NOT valid\n");
            return 0;
        }
        else {
            printf("valid\n")
            return 1;
        }
    }  
    

    它所做的是验证字符是否是utf-8中的有效字节。 0xFF和0xFE在utf-8中不是有效字节。 想象一下,如果函数将其验证为有效字节,会出现什么问题?

    发生了什么事:

    0xFE
    = 
    11111110 
    = 
    254
    

    如果将其保存在普通字符(带符号)中,则最左边的位(最有意义的位)将变为负数。但是它是什么负数呢?

    它通过翻转位并添加一位来实现这一点。

    11111110
    00000001
    00000001 + 00000001 =
    00000010 = 2
    

    记住它是负的,所以它变成-2

    所以函数中的(-2==0xFE)不是真的。

    因此,检查无效字节的函数最终会验证未验证的字节,就好像它们是正常的一样:-o。

    在处理utf-8时,我还可以想到另外两个坚持使用unsigned的原因:

    1. 如果您可能需要向右移位,可能会出现问题,因为如果使用有符号字符,那么您可能会从左侧添加1。

    2. utf-8和unicode只使用正数,所以。。。你为什么不呢?保持简单:)

    推荐文章