Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过将char强制转换到USHORT获得错误的UTF-8值_C_Linux_Gcc_Buildroot - Fatal编程技术网

通过将char强制转换到USHORT获得错误的UTF-8值

通过将char强制转换到USHORT获得错误的UTF-8值,c,linux,gcc,buildroot,C,Linux,Gcc,Buildroot,这是我在这里的第一个问题,如果我遗漏了重要的规则,请随意批评或纠正我 最近,我的任务是将旧的DOS C代码移植到Linux平台。字体处理是通过bitfonts实现的。我编写了一个函数,如果将正确的Unicode值传递到该函数中,该函数能够绘制选定的glyph 但是,如果我尝试将字符强制转换为USHORT(函数需要这种类型),当字符位于ASCII表之外时,我会得到错误的值 char* test; test = "°"; printf("test: %hu\n",(USHORT)test[0]);

这是我在这里的第一个问题,如果我遗漏了重要的规则,请随意批评或纠正我

最近,我的任务是将旧的DOS C代码移植到Linux平台。字体处理是通过bitfonts实现的。我编写了一个函数,如果将正确的Unicode值传递到该函数中,该函数能够绘制选定的glyph

但是,如果我尝试将字符强制转换为USHORT(函数需要这种类型),当字符位于ASCII表之外时,我会得到错误的值

char* test;
test = "°";

printf("test: %hu\n",(USHORT)test[0]);
显示的数字(控制台)应为176,而不是194

如果使用“!”将显示正确的33值。 我通过设置GCC编译器标志来确保char没有签名

-unsigned-char
GCC编译器使用UTF-8编码作为默认值。我真的不知道现在的问题在哪里

我是否需要向编译器添加另一个标志

更新

在@Kninnug answer的帮助下,我成功地编写了一个代码,它将为我生成所需的结果

#include <stdio.h>
#include <locale.h>
#include <string.h>
#include <wchar.h>
#include <stdint.h>

int main(void)
{
   size_t n = 0, x = 0;
   setlocale(LC_CTYPE, "en_US.utf8");
   mbstate_t state = {0};
   char in[] = "!°水"; // or u8"zß水"
   size_t in_sz = sizeof(in) / sizeof (*in);

   printf("Processing %zu UTF-8 code units: [ ", in_sz);
   for(n = 0; n < in_sz; ++n)
   {
      printf("%#x ", (unsigned char)in[n]);
   }
   puts("]");

   wchar_t out[in_sz];
   char* p_in = in, *end = in + in_sz;
   wchar_t *p_out = out;
   int rc = 0;
   while((rc = mbrtowc(p_out, p_in, end - p_in, &state)) > 0)
   {
       p_in += rc;
       p_out += 1;
   }

   size_t out_sz = p_out - out + 1;
   printf("into %zu wchar_t units: [ ", out_sz);
   for(x = 0; x < out_sz; ++x)
   {
      printf("%u ", (unsigned short)out[x]);
   }
   puts("]");
}
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
尺寸n=0,x=0;
setlocale(LC_CTYPE,“en_US.utf8”);
mbstate_t state={0};
[]中的字符=“!”水"; // 或u8“zß水"
尺寸t英寸=尺寸f(英寸)/尺寸f(*英寸);
printf(“处理%zu UTF-8代码单位:[”,单位为_sz);
对于(n=0;n0)
{
p_in+=rc;
p_out+=1;
}
大小(out)(sz)=p(out)out-out+1 ;;
printf(“转换成%zu wchar\t单位:[”,out\u sz);
对于(x=0;x
但是,当我在嵌入式设备上运行此操作时,非ASCII字符会合并到一个wchar中,而不是像我的计算机上那样合并到两个wchar中

我可以在cp1252中使用单字节编码(这很好),但我希望继续使用unicode。

A
char
signed
unsigned
)在C1中是单字节。
(USHORT)test[0]
只强制转换
test
中的第一个字节,但它的字符在UTF-8编码中占2个字节(您可以使用
strlen
检查,它统计第一个0字节之前的字节数)

要获得正确的代码点,您需要解码整个UTF-8序列。您可以使用和相关函数执行此操作:

char* test;
test = "°";
int len = strlen(test);

wchar_t code = 0;
mbstate_t state = {0};

// convert up to len bytes in test, and put the result in code
// state is used when there are incomplete sequences: pass it to
// the next call to continue decoding
mbrtowc(&code, test, len, &state); // you should check the return value

// here the cast is needed, since a wchar_t is not (necessarily) a short
printf("test: %hu\n", (USHORT)code); 
旁注:

  • 如果
    USHORT
    为16位(通常情况下),则它不足以覆盖整个UTF-8范围,而整个UTF-8范围需要(至少)21位

  • 获得正确的代码点后,不需要强制转换将其传递给绘图函数。如果函数定义或原型可见,编译器可以自行转换值



1这个令人困惑的名称来自于所有ASCII码点都可以放在一个字节中的时间。因此,一个字符与一个字节相同。

codepoint 176编码在一个两字节utf8序列中:
C2 B0
您只打印此序列的第一个字节。在程序源代码中不要使用任何非ASCII字符。避免使用我们在任何调用标准C库函数的程序中使用ing
-unsigned char
。当您说要将°编码为176时,您指的是哪个字符集和编码?UTF-8是Unicode字符集的字符编码。如果您需要匹配“旧DOS”",在英语中,字符集很可能是CP437,但有143个。我被迫在程序源代码中使用非ASCII字符,因为它将是遗留代码,现在不应更改。编译器标志
-unsigned char
是否会破坏任何标准C函数?要开始,请使用
wchar
not
char
,当然用户输入的课程和阅读应使用宽字符功能,任何显示器应使用“带mbrtowc”的宽字符功能只需使用
L'…'
宽字符直接到达代码点,无需转换。但在文本中使用非ascii内容是危险的,可以使用
L'\u1234'
表示法。不用等一分钟,为什么不直接使用
\x1234
?当然还需要转换从文件加载的数据。当我使用这种方法时
code
不会更改为
test
中的值,相反,它会保留第一个赋值。
mbrtowc
看起来很有希望,但我似乎无法使该函数正常工作。这可能是某种编译器问题吗?但是,我会从该函数中获取Unicode码点还是其他什么?我忘了提到它当我使用
test=“””
时,我得到-1作为
mbrtowc
的返回值,但当
test=“!”
或任何其他ASCII字符时,我得不到-1。当我声明字符无符号时,我至少可以提取编码的“°”的两个字节
printf(“测试:%hu\n”,(USHORT)测试[0])
打印194和
printf(“测试:%hu\n”,(USHORT)测试[1])
打印176,这是字符的正确编码。