C/C++走过的坑(基础问题篇)
1.有符号int与无符号int比较
#define TOTOL_ELEMENTS (sizeof(a) / sizeof(a[0]) ); int main()
{
int a[] = {23,24,34};
int d = -1;
if(d<=TOTOL_ELEMENTS)
printf("TRUE\n");
else
printf("FLASE\n"); return 0;
} //结果是FLASE而不是TRUE
结果分析:sizeof() 返回的是无符号整型,因此上述代码中TOTOL_ELEMENTS 的值是unsigned int类型。与 if 语句中signed int 型的 d 比较,signed int 型会被转化成unsigned int 型变量。
-1会转化成一个非常巨大的数---65535
*************************************************************
原码、反码、补码:
原码:二进制定点表示法,即最高位是符号位。0为正,1为负。
反码:正数的反码与原码相同;负数的反码是对其原码逐位去反,符号位除外。
补码:正数的补码与原码相同;负数的补码是在其反码末位上加1。
在计算机中,数值一律用补码存储,因为其能将符号位与数值统一处理。
********************************************************************
以int型的-1为例:
-1是负数,原码为 10000000 00000001 (int为2字节)
反码为 11111111 11111110
补码为 11111111 11111111
那么有符号怎么转化成无符号的呢?直接取绝对值的补码就行了。算术解决: |a|*2-|a| = 无符号的a
int a = -1;
(unsigned int)a= ?
(1)先取-1 的绝对值1的原码 00000000 00000001
(2)将其转化为反码 01111111 11111110
(3)对所求的数+1得到补码。补码就是无符号char的a值,转换为十进制数为65535
所以(unsigned int)a=65535;
另外,注意:printf函数输出的是无符号的值!!
附:(转)C语言符号扩展知识讲解http://blog.csdn.net/u010069213/article/details/24012649
2.位域变量 的符号问题
#include <stdio.h> struct data
{
int flag: 1;//;或者,都是允许的
int other: 31;
}; int main()
{
struct data test;
test.flag = 1;
if (test.flag == 1)
printf("test.flag =1,it is true\n");
else
printf("test.flag !=1,it is flase\n"); return 0;
}
输出:test.flag !=1,it is flase
分析:flat 是 int型的位域变量,用一个bit来表示int时,这一位是用来表示符号位的,带符号的一个bit的位域变量的取值范围是0或者-1(无符号的一个bit的位域变量的取值范围是0或者1)!!
当1赋值给test.flag时候,test.flag溢出,变为 -1......
将结构体改为一下代码即可:
struct data
{
unsigned int flag: 1;//;或者,都是允许的
int other: 31;
};
3.整除的精度问题
int main()
{
float result;
result = 1/6;
printf("result= %f\n",result);
return 0;
}
输出: 0
分析:1和6都是整型变量,两个整型变量结果依然是整型,不会保留整数部分。(毕竟是先运算再等号的)
修改:把 1 或者 6 的至少一个改为浮点类型表示即可!
在C语言中存在隐式类型转换:
(1)赋值时一律是右边值转化为左边,但是右边是表达式时,会先进行运算,然后才对运算的结果进行数据类型转换。
(2)当不同类型的变量进行计算时,遵循由低级向高级转换原则。如:char-->int ,short-->int , float -->double。。。。
4.浮点数的比较精度问题
int main()
{
float f = 1.0/3.0;
float expect_f = 0.333333333;
double d = 1.0/3.0;
double expect_d = 0.333333333;
printf("f = %f, expect_f = %f, d = %lf, expect_d = %lf\n",f,expect_f,d,expect_d );
if (f==expect_f && d == expect_d)
printf("equal!!\n");
else
printf("not equal!!!\n");
}
输出:
f = 0.333333, expect_f = 0.333333, d = 0.333333, expect_d = 0.333333
not equal!!!
分析:浮点数表示精度的位数有限,不能准确表示一个小数(IEEE754规定:单精度的float数据类型7位有效数字,double16位有效数字)
=====》浮点数比较时,一般比较他们之间的差值在一定范围内
将 if 的条件部分改为以下:
if (fabs(f-expect_f)<0.000001 && fabs(d == expect_d)<0.000001)
printf("equal!!\n");
5.最小整数取相反数溢出
int main()
{
int a = 0xffffffff;
if(a<0)
a = -a;
printf("a =%d \n",a); return 0;
}
结果:a = 1
分析:有符号的数据类型,有正负之分,如int,double,float...溢出后去反,得到a = 1
解决:对int数据类型进行去反处理时候,需要额外处理这种情况,添加以下代码:
else if (a == 0xffffffff)
printf("a = %d\n",a );
6.临时变量溢出问题
long multiply(int m,int n)
{
long score;
score = m*n;
return score
}
分析:m,n的相乘结果会先存储在一个临时的int变量中,然后再赋值给long变量score,这个临时变量容易溢出。所以在表达式运算前需要对m和n进行数据转换。
(64位平台,int 4bit, long 8bit--------------也不排除一些装了一些32位的软件,比如Dev-C++
32位平台,int 4bit,long 4bit)
无论怎样:一定要注意数据溢出问题!!
7.区分continue与return
return 用来返回某个值并退出程序;
continue 用于循环中,结束本次循环
8.指针常量与常量指针
指针常量:指针在常量前面。int *const 指针名 -------------指针本身是常量,它指向的地址不可以改变,但是地址内的数据可以根据指针的解引用改变!!
常量指针:常量在指针前面, const int *指针名 -----------指向常量的指针,顾名思义,指针指向常量,不可以指向变量!所以不能通过改变指向地址的内容!!,但是指针自身不是常量,自身的值可以改变,即指向哪个常量是可以改变的!
int main()
{
int a =2;
int b =4;
int *const pa = &a; //指针常量,只能改变地址内的内容
const int *pb = &b; //常量指针,只能改变地址 std::cout<< *pb <<endl;
std::cout<< *pa <<endl; pb=pa;
std::cout<< *pb <<endl; *pa = 343;
std::cout<< *pa <<endl;
输出:4 2 2 343
正确!!
9.字符数组和指针不总是相等的
在不同文件用extern引用的时候,字符数组和指针不是相等的!!
************************************************
不可以在a.cpp中:
char a[]="Hello world!";
然后在b.cpp中:
extern char *a; //WRORG
***********************************************
10.cin>>和 getline 混用导致的奇怪问题
cin 是c++标准输出流istream类型的对象,代表标准输出设备,相当于c中的stdin。程序中包含iostream头文件既可以使用 cin对象。istream类重载了抽取操作符">>",能够读取C++中的各种基础数据类型,抽取符“>>”根据后面变量的类型读取数据,从非空白符号开始没遇到Enter,Space,Tab结束
std::getline函数从istream中读取一行数据 遇到“\n”结束
#include <iostream>
using namespace std; int main()
{
int a;
string b;
cout<< "Please input a:"<<endl;
std::cin>> a;
// cin.ignore(); //默认cin::ignore(1,EOF) cout<< "Please input b:"<<endl;
std::getline(cin,b); cout<< "a:"<<a <<endl;
cout<< "b:"<<b<<endl; return 0; }
输出:b 的 值无法输入
解决:将注释那句激活
提醒:输入/输出 语句用一种就好了,不要混用
C/C++走过的坑(基础问题篇)的更多相关文章
- php支付走过的坑(微信篇 包含h5支付和app支付 注册 秘钥 环境等等配置)
支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...
- php支付走过的坑(支付宝篇 注册 秘钥 环境等等配置)
支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...
- 【转】8年!我在OpenStack路上走过的坑。。。
8年!我在OpenStack路上走过的坑... 摘要: 2010年10月,OpenStack发布了第一个版本:上个月,发布了它的第18个版本Rocky.几年前气氛火爆,如今却冷冷清清.Rocky版本宣 ...
- web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史
秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...
- 记一次ftp服务器搭建走过的坑
记一次ftp服务器搭建走过的坑 1.安装 ①下载 wget https://security.appspot.com/downloads/vsftpd-3.0.3.tar.gz #要FQ ②解压 ta ...
- javamail模拟邮箱功能发送电子邮件-基础实战篇(javamail API电子邮件实例)
引言: JavaMail 是一种可选的.能用于读取.编写和发送电子消息的包 JavaMail jar包下载地址:http://java.sun.com/products/javamail/downlo ...
- 【Java面试】基础知识篇
[Java面试]基础知识篇 Java基础知识总结,主要包括数据类型,string类,集合,线程,时间,正则,流,jdk5--8各个版本的新特性,等等.不足的地方,欢迎大家补充.源码分享见个人公告.Ja ...
- 安卓布局修改基础常识篇之TextView属性
[天使]安卓布局修改基础常识篇之TextView属性 在修改布局xml文件时需要熟练掌握一些属性,以下是TextView也就是文本的属性:android:autoLink 是否自动链接网址或邮箱地址: ...
- SQLAlchemy 教程 —— 基础入门篇
SQLAlchemy 教程 -- 基础入门篇 一.课程简介 1.1 实验内容 本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLA ...
随机推荐
- 前端测试框架 jasmine 的使用
最近的项目在使用AngulaJs,对JS代码的测试问题就摆在了面前.通过对比我们选择了 Karma + jasmine ,使用 Jasmine做单元测试 ,Karma 自动化完成,当然了如果使用 K ...
- 紧张:飞测独家のJmeter秘籍,限量发放
飞测说:数月前,小怪我牺牲了周末时间,做了fiddler的扩展开发,从fiddler将请求导出,保存为jmx格式的文件,然后使用jmeter来调用.随后,小怪和同事(心&阳)一同研究jmete ...
- 【测试】手工搭建DG
前言:(一)准备工作: 1.数据库要处于归档模式: 2.监听参数:local_listener 默认值为空--1521 3.关闭闪回(可能会触发数据库的bug,备库不能开闪回) 4.如果有外部表,外部 ...
- 学习练习 java 程序设计园的周长面积
编写一个Java程序,计算半径为3.0的圆周长和面积并输出结果. 注:系统类Math位于java.lang包中,圆周率π可以由Math类的静态属性PI得到,其定义为“public static fin ...
- 洛谷P1113 杂物
P1113 杂务 251通过 441提交 题目提供者该用户不存在 标签图论递推 难度普及/提高- 提交该题 讨论 题解 记录 最新讨论 为什么会只有10分? 题目描述 John的农场在给奶牛挤奶前有很 ...
- Android 类库打包、发布方法
开发Android应用的时候,对于可用于多个应用的公用的部分,或是打算发布给第三方进行应用集成的部分,要把这部分打包成类库怎么做呢? Android应用使用ADT打包成apk,apk中包含了运行程序所 ...
- Visual C++ 开发心得与调试技巧
自己平时收集的一些技巧与心得,这里分享出来,普及一下知识. 1.如何在Release状态下进行调试 Project->Setting=>ProjectSetting对话框,选择Releas ...
- Windows phone 8 学习笔记(8) 定位地图导航(转)
Windows phone 8 已经不使用自家的bing地图,新地图控件可以指定制图模式.视图等.bing地图的定位误差比较大,在模拟器中测试新地图貌似比较理想.本节主要讲解下位置服务以及新地图控件的 ...
- Windows phone 8 学习笔记(3) 通信(转)
Windows phone 8 可利用的数据通信方式比较广泛,在硬件支持的前提下,我们可以利用WiFi.蓝牙.临近感应等多种方式.数据交互一般通过套接字来完成,我们将在本文详细的分析. 快速导航:一. ...
- PHP生成静态页面的方法
在PHP网站开发中为了网站推广和SEO等需要,需要对网站进行全站或局部静态化处理,PHP生成静态HTML页面有多种方法,比如利用PHP模板.缓存 等实现页面静态化,今天就以PHP实例教程形 ...