关于有无符号数
2013-11-04 02:03
357 查看
《C专家编程》中对在使用有无符号数有的使用以下三点建议:
1.尽量不要在你的代码中使用无符号数,以免增加不必需要的复杂性。尤其是,不要仅仅因为无符号数不存在负值(如年龄,国债)而用它来表示数量。
2.尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译为非常大的正数)。
3.只有在使用位段和二进制掩码时,才可以用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号或无符号数,这样就不必由编译器来选择结果的类型。
1,2点可以合成一点,说的其实就是尽量不要使用无符号数,多使用有符号数,而第三点说明了无符号数的适用范围。并强调了在处理表达式的时候是操作数类型一致的原则(同为有符号或无符号),这样可以减少一些麻烦和错误。
另外,ANSI C在对有符号数和无符号数进行运算时也给出了一个标准(我在这里就不谈K&R C中的说法了):
当执行算术运算的时候,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。
下面有几个例子:
1.
#include <stdio.h>
#include <string.h>
int main()
{
int x = 2;
char * str = "abcd";
int y = (x - strlen(str) ) / 2;
printf("%d\n",y);
}
结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值,类型是size_t,也就是unsigned int ,与 int 混合计算时类型被自动转换了,结果自然出乎意料。。。
观察编译后的代码,除法指令为 div ,意味无符号除法,即将-2看做无符号数了。
解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成 idiv 了。
2.
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ”>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。
1.尽量不要在你的代码中使用无符号数,以免增加不必需要的复杂性。尤其是,不要仅仅因为无符号数不存在负值(如年龄,国债)而用它来表示数量。
2.尽量使用像int那样的有符号类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译为非常大的正数)。
3.只有在使用位段和二进制掩码时,才可以用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号或无符号数,这样就不必由编译器来选择结果的类型。
1,2点可以合成一点,说的其实就是尽量不要使用无符号数,多使用有符号数,而第三点说明了无符号数的适用范围。并强调了在处理表达式的时候是操作数类型一致的原则(同为有符号或无符号),这样可以减少一些麻烦和错误。
另外,ANSI C在对有符号数和无符号数进行运算时也给出了一个标准(我在这里就不谈K&R C中的说法了):
当执行算术运算的时候,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。
下面有几个例子:
1.
#include <stdio.h>
#include <string.h>
int main()
{
int x = 2;
char * str = "abcd";
int y = (x - strlen(str) ) / 2;
printf("%d\n",y);
}
结果应该是 -1 但是却得到:2147483647 。为什么?因为strlen的返回值,类型是size_t,也就是unsigned int ,与 int 混合计算时类型被自动转换了,结果自然出乎意料。。。
观察编译后的代码,除法指令为 div ,意味无符号除法,即将-2看做无符号数了。
解决办法就是强制转换,变成 int y = (int)(x - strlen(str) ) / 2; 强制向有符号方向转换(编译器默认正好相反),这样一来,除法指令编译成 idiv 了。
2.
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ”>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。
相关文章推荐
- 关于C语言有无符号数转换
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 关于.net后台innerHTML符号规则
- 关于PYTHON NUMPY数组的切片的符号省略问题
- 关于宏定义中#和##符号的使用和宏定义展开问题
- 关于取反的符号“~”“!”的疑问
- 关于货币符号以及发音、币别码
- 关于有符号数和无符号数的转换 - C/C++
- PHP 关于无符号整形Unsigned
- 关于Android的问号?和@符号的用法
- 关于硬链接和软连接(符号链接)的区别
- 关于CMake生成包含PCL库和CGAL库的工程时出现“无法解析的外部符号”的错误
- 关于C语言中的无符号数和有符号数
- 关于有符号数到无符号数的强制转换导致的一些问题
- 关于各种无法解析的外部符号问题的相应解决方案
- 关于java中有符号数转换成无符号数的相关问题
- C语言预处理功能 关于字符串化和符号粘贴
- 关于51单片机双字节(带有小数)无符号除法的问题
- Java中关于无符号右移的问题 (~0L>>>-5)当右边为负数的情况
- 关于URL中的特殊符号使用介绍