硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2407|回复: 13
收起左侧

[技术讨论] 汉字显示,汉字的字符串用char类型可以么?

[复制链接]

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
发表于 2021-7-12 15:44:11 | 显示全部楼层 |阅读模式
void LCD_DispStrEx(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont, uint16_t _Width,)这个函数字符串用char类型,如果是ascll码可以,汉字的话,汉字内码好像大于127,为啥还可以用char类型呢?

回复

使用道具 举报

0

主题

216

回帖

216

积分

高级会员

积分
216
发表于 2021-7-12 18:02:47 | 显示全部楼层
这里的char类型是指针,长度是不确定的,和硬件有关,比如32位系统上,就是32位的,64位系统上就是64位的。
编译器根据指针的类型去访问对应的地址取数据,如果是char(8位二进制数据类型)指针,就取1个字节,如果
是16位的数据类型,就取2个字节。
汉字需要软件去判断,根据编码不同,判断方式也不同。
在GB2312编码里,并不是所有的字符都会用两个字节来表示的。首先,ASCII编码虽然说是用一个字节来表示字符,但是它其实只用了后7位,第1位永远是0。它的编码范围,从00000000到01111111,都是以0开头的。  而GB2312编码,就是在ASCII编码的基础上进行扩充的,它规定了:ASCII的字符完整地包含在GB2312里,编码不变,仍然是以0开头,用一个字节来表示一个字符;对于ASCII没有的字符,就用1开头来区分,用两个字节合起来表示一个字符。  这样,在解码的时候,遇到字节是以0开头的,就知道这一个字节就表示了一个字符;遇到字节是以1开头的,就知道要加上下一个字节合起来表示一个字符。这样就在GB2312中既把ASCII的字符包含了进来,又能将它们区分出来,能达到兼容的效果了。
而UTF8编码更复杂一些。

评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2021-7-13 00:58:14 | 显示全部楼层
regbbs 发表于 2021-7-12 18:02
这里的char类型是指针,长度是不确定的,和硬件有关,比如32位系统上,就是32位的,64位系统上就是64位的。 ...



非常详细
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 08:25:29 | 显示全部楼层
regbbs 发表于 2021-7-12 18:02
这里的char类型是指针,长度是不确定的,和硬件有关,比如32位系统上,就是32位的,64位系统上就是64位的。 ...

比如我想用这个函数,显示     《春眠不觉晓》   ,     可以   char data[10]={"春眠不觉晓"};吗?春眠不觉晓的内码都大于127,感觉好像不太合适,?但是我申请u8 data[10],传入参数的时候会有警告,?
春B4BA
眠C3DF
不B2BB
觉BEF5
晓CFFE

回复

使用道具 举报

0

主题

216

回帖

216

积分

高级会员

积分
216
发表于 2021-7-13 09:05:27 | 显示全部楼层
ssssssss 发表于 2021-7-13 08:25
比如我想用这个函数,显示     《春眠不觉晓》   ,     可以   char data[10]={"春眠不觉晓"};吗?春眠 ...

字符串要比显示出来的多一个字节,要以0结尾,作为C库或者其他程序判断字符串是否结束。
空字符也要占用一个字节。
你这里的,5个汉字,如果用gb2312编码,汉字本身需要10个字节,结尾的0要占用一个,一共就是11个字节。
如果自己写,而且内容很确定,可以不要这末尾的0,但是需要用数组初始化的方式。
以GB2312编码字符为例:
u8 data[10] = "春眠不觉晓",这里编译器会提示data的空间不够,因为结尾的0还需要一个字节。
u8 data[10] = { 0xB4, 0xBA, ....., 0xFE},这样可以正好10个字节,但不能作为字符串参数传递给C库相应的函数。

回复

使用道具 举报

4

主题

117

回帖

129

积分

初级会员

积分
129
发表于 2021-7-13 09:12:04 | 显示全部楼层
ssssssss 发表于 2021-7-13 08:25
比如我想用这个函数,显示     《春眠不觉晓》   ,     可以   char data[10]={"春眠不觉晓"};吗?春眠 ...

是不是会默认成字符串结构啊?若是的话需要一个字符串结束符0x00这样就不够了
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 09:30:22 | 显示全部楼层
regbbs 发表于 2021-7-13 09:05
字符串要比显示出来的多一个字节,要以0结尾,作为C库或者其他程序判断字符串是否结束。
空字符也要占用 ...

char data[100]={"春眠不觉晓"};吗?春眠不觉晓的内码都大于127,感觉好像不太合适,(主要的意思不是说数组越界的问题)
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 09:35:35 | 显示全部楼层
regbbs 发表于 2021-7-13 09:05
字符串要比显示出来的多一个字节,要以0结尾,作为C库或者其他程序判断字符串是否结束。
空字符也要占用 ...

  char data[100]={"春眠不觉晓"};吗?春眠不觉晓的内码都大于127,感觉好像不太合适,?但是我申请u8 data[100],传入这个函数(void LCD_DispStrEx(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont, uint16_t _Width,))参数的时候会有警告,?
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2021-7-13 12:21:13 | 显示全部楼层
ssssssss 发表于 2021-7-13 09:35
char data[100]={"春眠不觉晓"};吗?春眠不觉晓的内码都大于127,感觉好像不太合适,?但是我申请u8 da ...

有啥不合适的?反正都是8bit,bit位信息又不会丢失?强制转换就行了。
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 13:12:57 | 显示全部楼层
ghslfgkkl88 发表于 2021-7-13 12:21
有啥不合适的?反正都是8bit,bit位信息又不会丢失?强制转换就行了。

以前一直认为,申请变量,变量的大小必须在数据类型的范围内,比如我申请char变量,那么变量肯定是-127到127,的范围,如果是申请u8,变量范围肯定要是0到255.这次有点颠覆我的观念了,有点想不通
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 14:21:24 | 显示全部楼层
本帖最后由 ssssssss 于 2021-7-13 14:39 编辑

硬汉大哥可否帮忙看看,我看刷汉字的函数里面code1<0x80,就表示ascll码,如果我申请一个char data[100]={“你”},高字节是-60,岂不是把你这个字识别成了ASCII码了?
回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-13 14:33:37 | 显示全部楼层
ghslfgkkl88 发表于 2021-7-13 12:21
有啥不合适的?反正都是8bit,bit位信息又不会丢失?强制转换就行了。

我们可以看到:char类型的取值范围为[-128 ~ 127],但是我们却可以打印出汉字”你“。这是为什么呢?明明char的取值范围最多127,而汉字“你”的两个字符分别为:196和227,都超过了这个值。其实这是因为,C语言将这两个数字的二进制数作为负数处理。C中的char类型有1个字节,占8位,而它的最高位为符号位,当它为0时为正,1时则为负。C通过对正数做补码操作得到负数。补码,即对一个二进制数取反,然后再加1。比如,0xC4的二进制数为0b11000100,我们可以看到最高位1,在C中这个数就是负数。我们可以通过对这个二进制数做补码操作,得到0b00111100,即60。所以0b11000100在C中表示为-60。



  从以上,我们可以发现,GBK编码中,一个汉字占两字节。因为C中char类型只占一个字节,所以需要使用两个char类型来表示汉字。因为C中char为有符号类型,char的表示范围为[-128 ~ 127],所以在遇到大于127的数字时,会被char表示为负数。

  其实,我们还可以使用unsigned char来实现。char默认是有符号的,取值范围为:-128 ~127。而unsigned char的取值范围则为:0~255,那么汉字“你”的编码就会被显示为:196和227。

https://www.cnblogs.com/noonjuan/p/12319727.html


回复

使用道具 举报

96

主题

297

回帖

585

积分

金牌会员

123

积分
585
 楼主| 发表于 2021-7-14 08:34:07 | 显示全部楼层
regbbs 发表于 2021-7-13 09:05
字符串要比显示出来的多一个字节,要以0结尾,作为C库或者其他程序判断字符串是否结束。
空字符也要占用 ...

谢谢解答,不过还是有疑问,,刷汉字的函数里面code1<0x80,就表示ascll码,如果我申请一个char data[100]={“你”},高字节是-60,岂不是把你这个字识别成了ASCII码了?
回复

使用道具 举报

39

主题

929

回帖

1051

积分

至尊会员

积分
1051
发表于 2021-7-15 10:14:29 | 显示全部楼层
ssssssss 发表于 2021-7-13 13:12
以前一直认为,申请变量,变量的大小必须在数据类型的范围内,比如我申请char变量,那么变量肯定是-127到 ...

请问你是什么专业的?看起来是没学过数字电路。你看到的只是现象,你应该透过现象看本质。

比如-1和255,你只从人类的视觉看到了-1和255是两个不同的数字。但如果你站在CPU的视觉看本质的话,你会发现他们在内存中存放的值都是0xFF(0b11111111)。

那么问题来了,假如你是CPU,你读到0xFF这个数,你觉得他是-1还是255?CPU是不认识-1或者255的,它只认识0xFF。如果CPU用无符号指令处理,那0xFF就被当成255处理了。如果CPU用有符号指令处理,那0xFF就被当成-1处理了。

CPU怎么处理,需要编译器告诉它;而编译器怎么处理,需要写代码的告诉它。

你写下代码 char a = -1; 就是你告诉编译器:a是有符号数,并给它赋值-1。然后编译器告诉CPU:a是0xFF,用有符号指令处理。


回到字符'你','你'的GBK编码是0xC4E3,无论你把'你'放在char中,还是放在uchar中,CPU读到的都是0xC4E3,明白吗?所以编程语言中的强制类型转换就是理解本质后的一种处理。对于char a = -1;程序员需要它是255时就用(uchar)a,需要它是-1是就是a。反过来也一样,对于uchar a = 255;程序员需要它是-1时就用(char)a,需要它是255时就是a。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-16 05:18 , Processed in 0.287549 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表