C++中char类型的溢出问题
C++中什么经常会运用到char类型,也会将char类型作为循环语句的循环条件,但往往这里最容易出现错误,容易出现溢出,进入死循环。这里我们就来简单介绍下为什么会出现这种情况。
首先,了解下char类型的取值范围:
char分为无符号(unsigned)和有符号(signed)两种:
无符号(unsigned)的取值范围:0~255;
有符号(signed)的取值范围为:-128~127.
一般我们常用char来声明一个变量,编译器默认为有符号的,即范围为:-128~127.
常见溢出问题:
知道了char类型的取值范围后,就容易理解为什么会出现溢出了。出现溢出的地方很多都是因为将char类型的变量作为了循环语句的条件部分,这样就很容易出现溢出,这里讲解一下char类型的自增情况。
一般作为循环条件时,char类型往往被赋值了int类型,如char i = 0,然后i进行自增。
当i是无符号型时,取值范围为-128 ~ 127,当i=127后再进行自增的时候,这时i就不是等于128了,而是等于-128;当i= -128,再进行自减的时候就不是等于-129,而是等于127.
当i是有符号型的时候,取值范围为0 ~ 255,当i = 255时,再进行自增,这时i=0,而不是等于256;当i=0,进行自减的时候i= 255,而不是-1.
这是因为char型对于有符号型,前24位永远和倒数第8位一样,对于无符号型,前24位永远为零。
造成上面的结果的原因:
当为有符号型时,当i = 127时,二进制为:0....0 0111 1111,然后加1后,按照上面的原理,变为:1....1 1000 0000,结果i = -128;当i=-128时,减1,二进制变为:0....0 0111 1111,结果i = 127.
当为无符号时,当i=255时,二进制为:0....0 1111 1111,加1后,按照上面的原理,变为:0....0 0000 0000 ,结果为i= 0;当i = 0时,减1,二进制为:0...0 1111 1111,结果为255.
下面通过一个实例来说明:
#define s8 char
static int k = 0;
void func()
{
s8 i = 0;
for(i = 0; i < 128; i++)
{
k += i&3;
}
printf("k = %d\n", k);
}
这里很多人可能会动笔就计算,算得 k= 192,但结果是错的。
原因:注意i为一个char类型,且为有符号型,并被赋初值0,这里当i = 127的时候,程序会正常进行,然后i自增,变为-128,最后还是满足条件,程序并不会终止,这样就出现了char类型的溢出,程序进入死循环。此时,要么改变循环中的条件,改为:i < 127;或者将i的类型改为int型。
C++中char类型的溢出问题的更多相关文章
- 在vs中char类型的实参与LPCWSTR类型的形参类型不兼容怎么解决?
今天在做 COS脚本解释器的时候,遇到了这个问题 先了解一下 LPCTCHAR 这个东东 LPCTSTR用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏,那么 ...
- 加深关于Java中char类型的理解
1.JAVA中,char占2字节,16位.可在存放汉字 2.char赋值 char a='a'; //任意单个字符,加单引号. char a='中';//任意单个中文字,加单引号. char a=1 ...
- C#和C++中char类型的区别
对于char,这个字符类型.我们一般都认为就是一个字节.今天在仔细比较发现,C#的char和C++的char是有区别的. 1.首先来看C#中char占多大空间 using System;using S ...
- 怎么解决ORACLE 中 CHAR类型的索引问题
在很多场景中,都有如下情况 trim(a.colunm1) = trim(b.colunm2) 应该怎么优化呢? 用到 TRIM 的很多原因是某些系统为了提高查询效率,不使用 ORACLE 的特有的 ...
- C中char类型的用法
代码 /* char类型的用法 */ #include <stdio.h> main(int argc, char *argv[]) { /* 声明字符变量c1 */ char c1 = ...
- c++中char类型字符串拼接以及int类型转换为char类型 && 创建文件夹
如下所示: #include <iostream> #include <windows.h> #include <cstring> using namespace ...
- C++中char类型的十六进制字符串转换成字节流
如a[5]="1234"转换成a[5]={0x12,0x34} 代码如下: void HexStrToByte(const char* source, unsigned char* ...
- c++中char类型的取值范围
-128~127,数字在计算机中以补码形式存储,因为正数的补码就是其本身且正数符号位置0,故最大值为01111111(一个0七个1)也就是127 而负数是对应正数值取反加一,拿最大的负数-1来说,就是 ...
- C#中char空值的几种表示方式
C#中char空值的几种表示方式 在C#中char类型的表示方式通常是用单引号作为分隔符,而字符串是用双引号作为分隔符. 例如: 程序代码 程序代码 char a = 'a'; char b = 'b ...
随机推荐
- nodejs+express blog项目分享
项目简介:项目采用nodejs+express+typescript+mongodb技术搭建 主要功能: 1.用户注册 2.用户登录 3.文章管理模块 4.图片管理模块 5.token认证 6.密码加 ...
- CoolBlog开发笔记第5课:请求与响应
教程目录 1.1 CoolBlog开发笔记第1课:项目分析 1.2 CoolBlog开发笔记第2课:搭建开发环境 1.3 CoolBlog开发笔记第3课:创建Django应用 1.4 CoolBlog ...
- Linux命令之文件搜索
locate 文件名 locate只能搜索文件名,不能搜索文件大小.搜索速度快. locate并不会搜索到那些新加入的文件.新加入文件后,使用updatedb,更新数据库后,再使用locate搜索. ...
- Populating Next Right Pointers in Each Node(I and II)
Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...
- Java Web开发中路径问题小结
Java Web开发中,路径问题是个挺麻烦的问题,本文小结了几个常见的路径问题,希望能对各位读者有所帮助. (1) Web开发中路径的几个基本概念 假设在浏览器中访问了如下的页面,如图1所示: 图1 ...
- 学习jQuery必须知道的几种常用方法
jQuery事件处理 ready(fn) 代码: $(document).ready(function(){ // Your code here...}): 作用:它可以极大地提高web应用程序的响 ...
- 以太坊智能合约虚拟机(EVM)原理与实现
以太坊 EVM原理与实现 以太坊底层通过EVM模块支持合约的执行与调用,调用时根据合约地址获取到代码,生成环境后载入到EVM中运行.通常智能合约的开发流程是用solidlity编写逻辑代码,再通过编译 ...
- Day9 进程同步锁 进程队列 进程池 生产消费模型 进程池 paramike模块
进程同步锁: 当运行程序的时候,有可能你的程序同时开多个进程,开进程的时候会将多个执行结果打印出来,这样的话打印的信息都是错乱的,怎么保证打印信息是有序的呢? 其实也就是相当于让进程独享资源. fro ...
- 关于期权池Option Pools与Vesting:码农创业防身必备法器
之前又看到饿了么创始人团队纠纷的几篇文章,参考了百科.wiki.36Kr.虎嗅.知乎以及邵亦波老师的文章,对之前一直感兴趣的期权汇编初略总结了下 ,仍觉粗糙,对一些具体操作还是不甚了了,不过感觉在中国 ...
- 使用Node.js完成的第一个项目的实践总结
http://blog.csdn.net/yanghua_kobe/article/details/17199417 项目简介 这是一个资产管理项目,主要的目的就是实现对资产的无纸化管理.通过为每个资 ...