请进,关于C语言,一道经典面试题目

时间:2021-05-04 21:58:04
题目如下:

引用
13. 评价下面的代码片断:

unsigned int zero = 0; 
unsigned int compzero = 0xFFFF; 
/*1's complement of zero */

对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

unsigned int compzero = ~0;

这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。 
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧…


字长的事情我清楚,不清楚地是,这里的 “~0” 代表什么?求指教!

再有,第一行语句:
unsigned int zero = 0;
应该没有问题吧,谢谢!

71 个解决方案

#1


只为娱乐

#2


求反. ~00000000000000000000000000000000为11111111111111111111111111111111.不知机长多少位?

#3


二进制取反

#4


您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办

unsigned int compzero = ~0;
~0是在说我不管你是两字节还是四字节我只要全1,系统你自己去自适应去,所以写成~0,这样在两字节机器上系统会自动变成0xFFFF,四字节机器上变成0xFFFFFFFF保证了你的意图

#5


这道题的意思是如果在16位的机器上,这样定义unsigned int compzero = 0xFFFF;就会出现问题,而这样定义unsigned int compzero = ~0;就可以保证代码良好的可移植性

#6


魏士兵:“怎。。。”

#7


按位取反。

#8


~0就是对0各位取反,因为不知道位数,所以只要对0取反就可以知道最大值是多少。

#9


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……


多谢,问一下
unsigned int compzero = (unsigned int)(-1);
,效果也是不是一样啊

#10


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编并单步执行一遍不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编并单步执行。)

#11


我还以为 lz 在面试别人

#12


我是学习电信专业的,先接触的是硬件的东西,我理解程序就是从硬件想的,而不是编译器!所以我可能会考虑到这些。但是这些东西似乎没的啥子意义!啥子东西出现在中国都不应该奇怪,这句话太对了!

#13


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……

++

#14


该回复于2011-05-18 09:26:15被版主删除

#15


似乎这样也行。。。

unsigned int compzero =  -1;

请进,关于C语言,一道经典面试题目

#16


-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

#17


增加代码的移植性,我还真没有想到。
学习了,学习了~~~

#18


引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

平时接触的都是32位的,16位-1为什么要强制转换为(unsigned int),期待解答。

#19


混 CSDN就是好  长见识啊 
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用    

#20


无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的数据。

比如16位系统中一个int能存储的数据的范围为-32768~32767,而unsigned能存储的数据范围则是0~65535。

由于在计算机中,整数是以补码形式存放的。根据最高位的不同,如果是1,有符号数的话就是负数;如果是无符号数,则都解释为正数。同时在相同位数的情况下,所能表达的整数范围变大。

如果表达式中既有int 又有unsigned int,则所有的int数据都被转化为unsigned int类型。

这就是16位-1为什么要强制转换为(unsigned int).......
 
经过这番总结,前面提出的问题的答案应该就很明显了吧。-1必须转换为unsigned int型,32位即0xffffffff,很显然溢出了。

#21


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……

+1

#22


引用 17 楼 jobszheng5 的回复:
增加代码的移植性,我还真没有想到。
学习了,学习了~~~

这是一道面试嵌入式系统的题目中的一题,所以要考虑移植性,原文我也看过。 请进,关于C语言,一道经典面试题目

#23


引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

#24


该回复于2011-05-18 10:26:55被版主删除

#25


引用 6 楼 dingwo006 的回复:
魏士兵:“怎。。。”

才是破个LC,怎你妹的

#26


引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,111111111111110 加上符号位,整体+1  全是1

#27


嵌入式如果用int关键字才是真正不懂嵌入式,
如果想做到软件可以移植,应该将类型给定义清晰,

typedef unsigned char       INT8U; 
typedef signed   char       INT8S;
编码时使用INT8U去定义数据类型。

明知道int在不同的机器上可能有不同的字长,还使用int,自找苦吃。

#28


引用 26 楼 gykuku 的回复:
引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1 最高位为1 其余15位取绝对值原码 000000000000001 然后这15位取反,111111111111110 加上符号位,整体+1 全是1

++
是16个1,在计算机系统中,数值一律用补码来表示(存储)

#29


一看题目,莫名奇妙。
一看答案,恍然大悟。
牛啊~~~~

#30


我现在写,一直以来都只关注32位,不是我不晓得这个int的可移植性,是没一直考虑着个问题。
受教了。

#31


学习了!

#32


引用 26 楼 gykuku 的回复:
引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,111111111111110 加上符号位,整体+1  ……

这位仁兄说的太对了、、、就应该这样。。
一切都宏定义好。

#33


引用 19 楼 unix_architect 的回复:
混 CSDN就是好  长见识啊 
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用


牛人说的:以其写三流的代码不如用心看一流的代码

#34


看到楼主这个题目让我想到两个情景:

1.用c/c++编程时要注意结构体、类的编写,也会遇到字长和对齐问题。如,
struct t
{
    int i;
    char c0;
    double d;
    char c1;
}
这种是不好的编程方式。

2.有本书上好像讲了不同平台的字节数和对齐问题,哪本书讲不清了,可能是apue吧。 
  不同平台下很多数据类型长度是不同的,好像有个折中的办法来尽量使程序可移植。

#35


不错,非常经典,受益匪浅

#36


引用 27 楼 vimney 的回复:
嵌入式如果用int关键字才是真正不懂嵌入式,
如果想做到软件可以移植,应该将类型给定义清晰,

typedef unsigned char       INT8U; 
typedef signed   char       INT8S;
编码时使用INT8U去定义数据类型。

明知道int在不同的机器上可能有不同的字长,还使用int,自找苦吃。


我晕,这都点错了,这才是最好的办法、
一切都自定义好。

#37


长见识了

#38


帮顶!!!

#39


很好!!!!

#40


引用 32 楼 j307533688 的回复:
引用 26 楼 gykuku 的回复:

引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,11111……



我承认  错误有2个,一个引用点错人了。。。
还有最大的错误是  typedef  自定义类型,误说成宏定义了,
宏定义是 define/

5555泪奔啊

#41


呵呵学习了

#42


抛开字长。

-1就是 无符号整形的最大值。
~0就是取反。变成(1)*

不知道楼主的题目为什么会在 32位下这样使用:x = 0xFFFF
至少明了点也得这么写吧:x = 0xFFFFFFFF
你看Windows.h的文件就知道了。
有(-1),有(~0),有0xFFFFFFFF的写法。

#43


用什么系统和环境的人都有,所以感觉以上没有答案是全面的,还盼有更完善的说法.

#44


顶下用什么系统和环境的人都有,所以感觉以上没有答案是全面的,还盼有更完善的说

#45


学习!! 好多技巧

#46


说得也有道理啊

#47


引用 33 楼 long2015 的回复:
引用 19 楼 unix_architect 的回复:

混 CSDN就是好 长见识啊
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用


牛人说的:以其写三流的代码不如用心看一流的代码

程序员面试宝典里的。。。呵呵

#48


不太懂啦!!

#49


该回复于2011-05-20 08:54:13被版主删除

#50


-1在16位机器上表示为1000000000000001,怎么会时这个样子呢?奇怪?

#1


只为娱乐

#2


求反. ~00000000000000000000000000000000为11111111111111111111111111111111.不知机长多少位?

#3


二进制取反

#4


您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办

unsigned int compzero = ~0;
~0是在说我不管你是两字节还是四字节我只要全1,系统你自己去自适应去,所以写成~0,这样在两字节机器上系统会自动变成0xFFFF,四字节机器上变成0xFFFFFFFF保证了你的意图

#5


这道题的意思是如果在16位的机器上,这样定义unsigned int compzero = 0xFFFF;就会出现问题,而这样定义unsigned int compzero = ~0;就可以保证代码良好的可移植性

#6


魏士兵:“怎。。。”

#7


按位取反。

#8


~0就是对0各位取反,因为不知道位数,所以只要对0取反就可以知道最大值是多少。

#9


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……


多谢,问一下
unsigned int compzero = (unsigned int)(-1);
,效果也是不是一样啊

#10


计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构……

VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编并单步执行一遍不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编并单步执行。)

#11


我还以为 lz 在面试别人

#12


我是学习电信专业的,先接触的是硬件的东西,我理解程序就是从硬件想的,而不是编译器!所以我可能会考虑到这些。但是这些东西似乎没的啥子意义!啥子东西出现在中国都不应该奇怪,这句话太对了!

#13


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……

++

#14


该回复于2011-05-18 09:26:15被版主删除

#15


似乎这样也行。。。

unsigned int compzero =  -1;

请进,关于C语言,一道经典面试题目

#16


-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

#17


增加代码的移植性,我还真没有想到。
学习了,学习了~~~

#18


引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

平时接触的都是32位的,16位-1为什么要强制转换为(unsigned int),期待解答。

#19


混 CSDN就是好  长见识啊 
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用    

#20


无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的数据。

比如16位系统中一个int能存储的数据的范围为-32768~32767,而unsigned能存储的数据范围则是0~65535。

由于在计算机中,整数是以补码形式存放的。根据最高位的不同,如果是1,有符号数的话就是负数;如果是无符号数,则都解释为正数。同时在相同位数的情况下,所能表达的整数范围变大。

如果表达式中既有int 又有unsigned int,则所有的int数据都被转化为unsigned int类型。

这就是16位-1为什么要强制转换为(unsigned int).......
 
经过这番总结,前面提出的问题的答案应该就很明显了吧。-1必须转换为unsigned int型,32位即0xffffffff,很显然溢出了。

#21


引用 4 楼 ljt3969636 的回复:
您还是没太体会字长的重要

unsigned int compzero = 0xFFFF;
意图是想让compzero 全是二进制1,但是 0xFFFF是代表程序员认为int 是2个字节的,在两个字节的机器上这样可以要是4字节呢?系统就自动变成相当于unsigned int compzero = 0x0000FFFF;的形式这下和你的意图不一样了吧?

那我想在2或4字节都全1怎么办
……

+1

#22


引用 17 楼 jobszheng5 的回复:
增加代码的移植性,我还真没有想到。
学习了,学习了~~~

这是一道面试嵌入式系统的题目中的一题,所以要考虑移植性,原文我也看过。 请进,关于C语言,一道经典面试题目

#23


引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

#24


该回复于2011-05-18 10:26:55被版主删除

#25


引用 6 楼 dingwo006 的回复:
魏士兵:“怎。。。”

才是破个LC,怎你妹的

#26


引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,111111111111110 加上符号位,整体+1  全是1

#27


嵌入式如果用int关键字才是真正不懂嵌入式,
如果想做到软件可以移植,应该将类型给定义清晰,

typedef unsigned char       INT8U; 
typedef signed   char       INT8S;
编码时使用INT8U去定义数据类型。

明知道int在不同的机器上可能有不同的字长,还使用int,自找苦吃。

#28


引用 26 楼 gykuku 的回复:
引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1 最高位为1 其余15位取绝对值原码 000000000000001 然后这15位取反,111111111111110 加上符号位,整体+1 全是1

++
是16个1,在计算机系统中,数值一律用补码来表示(存储)

#29


一看题目,莫名奇妙。
一看答案,恍然大悟。
牛啊~~~~

#30


我现在写,一直以来都只关注32位,不是我不晓得这个int的可移植性,是没一直考虑着个问题。
受教了。

#31


学习了!

#32


引用 26 楼 gykuku 的回复:
引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,111111111111110 加上符号位,整体+1  ……

这位仁兄说的太对了、、、就应该这样。。
一切都宏定义好。

#33


引用 19 楼 unix_architect 的回复:
混 CSDN就是好  长见识啊 
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用


牛人说的:以其写三流的代码不如用心看一流的代码

#34


看到楼主这个题目让我想到两个情景:

1.用c/c++编程时要注意结构体、类的编写,也会遇到字长和对齐问题。如,
struct t
{
    int i;
    char c0;
    double d;
    char c1;
}
这种是不好的编程方式。

2.有本书上好像讲了不同平台的字节数和对齐问题,哪本书讲不清了,可能是apue吧。 
  不同平台下很多数据类型长度是不同的,好像有个折中的办法来尽量使程序可移植。

#35


不错,非常经典,受益匪浅

#36


引用 27 楼 vimney 的回复:
嵌入式如果用int关键字才是真正不懂嵌入式,
如果想做到软件可以移植,应该将类型给定义清晰,

typedef unsigned char       INT8U; 
typedef signed   char       INT8S;
编码时使用INT8U去定义数据类型。

明知道int在不同的机器上可能有不同的字长,还使用int,自找苦吃。


我晕,这都点错了,这才是最好的办法、
一切都自定义好。

#37


长见识了

#38


帮顶!!!

#39


很好!!!!

#40


引用 32 楼 j307533688 的回复:
引用 26 楼 gykuku 的回复:

引用 23 楼 mjjackey 的回复:
引用 16 楼 yoxibaga 的回复:
-1在16位机器上表示为1000000000000001,强制转换为(unsigned int),a=32769

要用补码吧,是16个1。

-1  最高位为1 其余15位取绝对值原码  000000000000001  然后这15位取反,11111……



我承认  错误有2个,一个引用点错人了。。。
还有最大的错误是  typedef  自定义类型,误说成宏定义了,
宏定义是 define/

5555泪奔啊

#41


呵呵学习了

#42


抛开字长。

-1就是 无符号整形的最大值。
~0就是取反。变成(1)*

不知道楼主的题目为什么会在 32位下这样使用:x = 0xFFFF
至少明了点也得这么写吧:x = 0xFFFFFFFF
你看Windows.h的文件就知道了。
有(-1),有(~0),有0xFFFFFFFF的写法。

#43


用什么系统和环境的人都有,所以感觉以上没有答案是全面的,还盼有更完善的说法.

#44


顶下用什么系统和环境的人都有,所以感觉以上没有答案是全面的,还盼有更完善的说

#45


学习!! 好多技巧

#46


说得也有道理啊

#47


引用 33 楼 long2015 的回复:
引用 19 楼 unix_architect 的回复:

混 CSDN就是好 长见识啊
我发现这程序真是学越越有意思啊 看看你们高手的回答 确实有用


牛人说的:以其写三流的代码不如用心看一流的代码

程序员面试宝典里的。。。呵呵

#48


不太懂啦!!

#49


该回复于2011-05-20 08:54:13被版主删除

#50


-1在16位机器上表示为1000000000000001,怎么会时这个样子呢?奇怪?