- 主题:上午面试了一个小孩,问了一个问题是不是太过分了 (转载)
具体哪个编译器在哪个平台上char是16位?确实从来没想过char可以不是一个byte,或者一个byte有16位,涨知识了。
【 在 feiy 的大作中提到: 】
: 竟然被转到这个版面来,还被顶上了十大,那么:
: 1、先说一下,这个题目是智能硬件嵌入式固件背景,随便考一下相关经验的,请不要忘
: 记了这个前提。
: ...................
--
修改:ilovecpp FROM 114.86.93.*
FROM 114.86.93.*
char的符号问题大家都知道。很多人不知道的是
“在一些场合,char会结合这平台按照16位处理的,比如IAR和CCS特别是针对TI的一
些平台”
也就是16位char。这个你可以具体说说。
【 在 feiy 的大作中提到: 】
: 不是奇葩,而是你做嵌入式固件的经验很一般没有遇到过或者不知道而已。
: 同时,如果你真的是搞技术做嵌入式的,那你发这个回帖(认为是奇葩)风格,的确是令人感到比较遗憾的。
:
: ...................
--
FROM 114.86.93.*
wchar_t大家都知道。可是你原话是
“在一些场合,char会结合这平台按照16位处理的”
你要写的是wchar_t我肯定不会问了。可你写的是char。
【 在 feiy 的大作中提到: 】
: 百度一下 wchar
:
--
FROM 114.86.93.*
嗯,查到了。谢谢。
char的符号问题或者int的位数,大部分C使用者都知道。而C标准允许大于8bit的char这一点,可能大部分人都认为只存在于理论上或者古代平台,确实没想到在现代硬件中还有。
【 在 feiy 的大作中提到: 】
: 自己百度一下 wchar 或者百度一下 char is 16-bit
: 此外,了解一下TI的一些嵌入式平台,比如CCS环境。在嵌入式上,char is 16-bit 的确比
: char is unsigned更少见,大多数都是8-bit的。所以,你不知道也没啥,做到某些嵌入式开发时,如果遇到了char is 16-bit的时候,别意外就是了,或者尤其是当进行参数传递时,发现出现了匪夷所思稀奇古怪的参数传递时,检查一下char是不是依然是8-bit的
: ...................
--
修改:ilovecpp FROM 114.86.93.*
FROM 114.86.93.*
类似memset, memcpy这种用途,还是应该用char。这里char并不是“字符类型”或者“整型”,而是“内存单元”。一个buffer的类型如果不是char*那应该是什么呢?
如果这里用u8,遇到像你说这种内存单元不是8位的就真错误了。而用signed/unsigned char的话,理论上有可能平台只能高效支持其中一种,另一种较低效。我想这也是C标准里char不默认为有符号的原因。
【 在 feiy 的大作中提到: 】
: 所以,规范公司和有经验的工程师都会拒绝用单独一个char(plain char),都会定义一套u8 s8 u16 s16之类的使用。
: 但现实里,却是有不少工程师有时会无意该地夹杂用char来表示他所本意的signed 8-bit,而且认为没错无问题。有时候,编译器会给warning,有时候未必会给warning(前面有人说char a=-5;很易被warning,但若-5是隐性计算出来的呢,编译器本身也并不总是很聪明),有很多人面对一大堆warning也习惯于忽略无视。
: 不是说一定会出问题bug,做多开发经验有了,一般基本都会遇到。
: ...................
--
修改:ilovecpp FROM 114.86.93.*
FROM 114.86.93.*
这个你说得不对。首先C语言不论指针的值还是sizeof,都是以char为单位的。不论它内部用什么指令实现,memcpy(dst,src,N)一定是复制了N个char。那么它最朴素的实现,也就是一个char*上的循环。
当然今天以前,我会觉得char不是8位只是理论上的可能性,你在memcpy里用u8也没问题。但是现在我们知道,确实有编译器可以设定为16位char,那么在此模式下memcpy的长度参数必定是以16位为单位计数的。如果两个指针的值差1,它们之间也必定差16位。
【 在 feiy 的大作中提到: 】
: 若想最终确认你的说法在各个场景对不对,最好的办法对着编译结果(上下几条汇编)看看吧,他用啥指令搬运,8位指令还是32位的搬运指令,也可能优化的目的,混杂都有。这是最靠谱方法。所以你说的不绝对,memcpy之类基本还是以8-bit字节为计数,指向的缓冲区或内存地址,依然可以视作是以字节为计数的,所以你用u8*大概率毫无问题(最多个可忽视不影响的warning),严格说来,u8*这是个指标本身不是8位的,可能是32位的。只是在某些平台某些场合上有类似32位对齐的要求,就是u8*这个指针的值(地址)必须是32位对齐的,但不代表是按32位复制,或必须是u16*或u32*。
: 不知我表达清楚没有,你酌情看吧。扯远了,估计一些人看着会懵认为是啥也没说瞎扯淡了。我的回答是,不一定,看编译结果。
: --来自微水木3.5.11
--
FROM 114.86.93.*
我说的不是符号问题。
我的意思是“记得标准库函数对后面的个数是以8-bit为单位”不对。memcpy, memset, sizeof都是以char为单位。
所以你要表示一个内存单位时就应该用char。用u8或s8都不对。
例如:
char buf[sizeof(MyStruct)*10];
而不是
u8 buf[sizeof(MyStruct)*10];
【 在 feiy 的大作中提到: 】
: 对于memset/memcpy,复制的数,分辨char带不带符号,其实没多大关系,因为只是个存储而已。一个8-bit空间全是bit1,若对应的变量是s8,那就按-1理解,若对应的是u8,那就按255理解而已。
: 是不是有符号的,主要在比较等场合会有影响。会影响编译器根据其符号选择不同的比较指令或处理方式。
: 很多加减场合基本无影响(当然,有些时候可能会牵涉到溢出位数转化,具体分析吧)。
: ...................
--
FROM 114.86.93.*
考虑到int全部默认signed,唯独char不同。大概是设计C语言时,各种cpu都能直接操作有符号word,而存在cpu(或者设计者以为存在cpu)只能操作无符号byte,有符号byte需要软件模拟。
【 在 adoal 的大作中提到: 】
: 其实PC上的编译器(至少VC是)也可以通过选项指定默认的char
: 是signed还是unsigned,只不过未指定时默认为signed罢了。
:
--
FROM 114.86.93.*
嗯C里char就是1 byte,所以16位char就意味着所有叫"byte"的都是16位,至少按照C标准来说应该是。
【 在 lvsoft 的大作中提到: 】
: 这个8位 16位 32位搬运指令混合只是实现过程中的优化带来的。所以他说的是memcpy的“最朴素”实现。
: 32位系统当然会尽可能发挥位宽优势,一般是用8位对齐,之后32位批量搬运,最后再8位解决剩下的。这个实现并不影响逻辑上的定义。
:
--
FROM 114.86.93.*
主要是没想到现在在售的硬件也有。
不过好像也不错,比如你只有16位地址线但你就是需要寻址256K*8bit,那么一个简单的解决办法就是...
【 在 adoal 的大作中提到: 】
: 我只知道上古平台有char可能是6或者7 bit的,还真不知道有>8的
--
修改:ilovecpp FROM 114.86.93.*
FROM 114.86.93.*