c语言整型和字符型的自动类型转换

char a = -1; //机器码为0xff
unsigned char b = 254; //机器码0xfe
if (a <= b){
  printf("a <= b\n");
}
else{
  printf("a > b\n");
}

上述代码输出结果: a > b

赋值用机器码写入内存

  虽然我们以十进制为两个变量赋值,但是变量值在内存中是以二进制机器码的形式存在。如果十进制数是负数,它就以补码的形式存放在内存中。比如"a = -1",a的真值以二进制表示为"1000 0001",高位是符号位,其余位表示绝对值;它的反码是"1111 1110",补码是"1111 1111",所以内存中某个存放变量a的字节的数是0xff。而正数的补码就是原码,不需要转换,所以内存中某个存放变量b的字节的数是0xfe。(有关机器码和补码知识请戳https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html

运行时不同类型变量的比较存在类型转换

  当正在比较的两个变量类型不同时,会发生类型转换。有符号char型和无符号char型比较时,有符号临时转换成无符号(机器码不变,只是编译器处理这个变量的方法改变)。a临时转成无符号后机器码仍然时0xff,但是编译器把它作为无符号处理——即没有符号位,取值范围时[0, 255],所以临时变量值是255,自然比b大。

  

  那么字符型和整型变量发生类型转换时需要注意哪些呢?

  一字节“字符型” -> (转换为)四字节“整型”,字节数较少的字符型变量会向高位扩展,具体补‘0‘还是补’1‘,根据字符型变量自身类型和高位符号两者决定。下面看四个例子。

例一:

char a = 0xff;
unsigned b = 0xffffffff;
if (a == b){
  printf("equal.\n");
}
else{
  printf("not equal\n");
}

上述代码输出结果:equal.即补‘1’.

例二:

char a = 0xff;
int b = 0xffffffff;
if (a == b){
  printf("equal.\n");
}
else{
  printf("not equal\n");
}

上述代码输出结果:equal.即补‘1’.

例二和例一只有变量b的类型不同,由此看出向高地址补位的动作不受要转向的那个类型所影响。

例三:

unsigned char a = 0xff;
unsigned b = 0xffffffff;
if (a == b){
  printf("equal.\n");
}
else{
  printf("not equal.\n");
}

上述代码输出结果:not equal.。即补‘0’。

例三和例一只有变量a的类型不同,由此看出向高地址补位的动作受变量本身类型所影响。

例四:

char a = 0x7f;
unsigned b = 0xffffffff;
if (a == b){
  printf("equal.\n");
}
else{
  printf("not equal.\n");
}

上述代码输出结果:not equal.。即补‘0’。

例四和例一只有变量a的值不一样,例四中变量a的高位是0,因此向高位补‘0’,由此有符号型向高地址补位的动作受变量符号位的值所影响。

  而四字节“整型”  -> (转换为) 一字节“字符型” ,就是单纯地把低位一字节的内容赋值给字符型变量。

char型数据溢出情况

char a = 64;
a *= 2;
if (a >= 0){
  printf("a >= 0");
}
else{
  prinf("a < 0");
}

上述代码输出结果:a < 0。

  虽然以十进制数‘128’赋值给变量,但实际存入内存中的机器码是0x80,编译时以有符号字符型处理这个字节。这个值符号位是‘1’,表示负数,对其余位求补码——结果换算成十进制,并加负号,就是这个机器码的真值,即‘-128’。所以小于‘0’。例子中虽然0x80在一个字节所能表示的数值范围内,但是超过char型所能表示的正数范围,这是char型数据溢出的一个例子。

unsigned char型数据溢出情况

unsigned char a = 128;
do {
    a *= 2;
    printf("%x", a);
} while (a <= 256)

上述代码会不停循环。

  当变量a从0x80乘2后,机器码是0x100。由于‘a’只能存储一个字节的数据,所以取结果的低位一字节,即0x00,这样从0 -> 255 -> 0循环下去。这是unsigned char型数据溢出的一个例子。

另外举一个误把unsigned char型当作负数处理地例子,虽然不可能发生,但有必要了解一下其中原因:

unsigned char a = 0x0a;
do {
    --a;
    printf("%x", a);
} while (a >= 0)

上述代码会不停循环。

  当变量a从0x0自减后,机器码是0xff。因为计算机运算中把减法当作两数的补码相加来做,(0 - 1)表达式在计算机运算中解释为(0x0 + 0xff),所以结果是0xff。

最后举一个char型最小负数取相反数溢出的例子:

char a = -128;
char b = -a;
if (b > 0){
  printf("b > 0\n");
}
else{
  printf("b <= 0\n");
}

上述代码输出结果:b <= 0。

  |a|的真值用二进制表示"1000 0000",用补码表示同样是"1000 0000",最后由于是负数,高位置为‘1’,结果是"1000 0000",这个0x80的char型机器码的特殊之处在于符号位同时表示数值。‘b’被编译器处理为-128,所以输出"b <= 0"。

原文地址:https://www.cnblogs.com/yichi/p/10089484.html

时间: 2024-08-29 07:44:57

c语言整型和字符型的自动类型转换的相关文章

Android - SpannableString或SpannableStringBuilder以及string.xml文件中的整型和string型代替

背景介绍 在开发应用过程中经常会遇到显示一些不同的字体风格的信息犹如默认的LockScreen上面的时间和充电信息.对于类似的情况,可能第一反应就是用不同的多个TextView来实现,对于每个TextView设置不同的字体风格以满足需求. 这里推荐的做法是使用android.text.*;和 android.text.style.*;下面的组件来实现RichText:也即在同一个TextView中设置不同的字体风格.对于某些应用,比如文本编辑,记事本,彩信,短信等地方,还必须使用这些组件才能达到

Python基本数据类型之整型和布尔型

整型和布尔型 获取对象的数据类型 1.type() 2.dir() 3.help() 4.在pycharm里面的操作 数字类型 int 创建: int() 接收数字字符串 .bit_lenght() int类型的长度 布尔类型 bool 获取对象的数据类型 1.type() 查看对象的数据类型 例子:(字符串) 1.s = "abc"2.print(type(s)) 结果: 1.<class 'str'> 2.dir() 查看对象对应类具备的所有方法 1.temp = &q

整型和字符切片转换

整数转换为字节切片思路:1.开辟一个字节集缓存区2.把整数写入到缓存区中3.将缓存区转换为字节切片注意: 方法binary.Write(io.Writer, ByteOrder, interface{})1.bytes.Buffer实现了io.Writer接口.写意味着别的数据写入自身(读则意味着自身数据放入其他地方)2.ByteOrder字节顺序3.interface{}任何类型都实现了空接口 func IntToHex(num64 int64) []byte { buff := new(by

C语言中字符型和字符串型的区别?

C语言中只有字符型类型,没有字符串型类型.字符类型用一个带符号的8位二进制编码表示,其性质与int相同,只是只有一个字节.表示字符的ASCII编码使用其中的0~127,所以要明白字符类型(char)其实是一个一字节整型,并不只用来表示字符.由于C中没有字符串类型,所以在处理字符串时是利用字符型数组来实现的,在字符型数组中一个接一个地存储字符的ASCII编码,并在最后一个字符后加一个'\0'表示这一串字符结束了,就形成所谓“字符串”.

Sql注入的分类:数字型+字符型

Sql注入: 就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.通过构造恶意的输入,使数据库执行恶意命令,造成数据泄露或者修改内容等,以达到攻击的目的.主要是由于应用程序对用户的输入没有进行严格的过滤而造成的. 一.万能密码 在说sql注入分类之前,先来看一下万能密码的构成原理.万能密码是由于某些程序,通过采用判断sql语句查询结果的值是否大于0,来判断用户输入数据的正确性造成的.当查询之大于0时,代表用户存在,返回true,代表登

基于python语言的tensorflow的‘端到端’的字符型验证码识别源码整理(github源码分享)

基于python语言的tensorflow的‘端到端’的字符型验证码识别 1   Abstract 验证码(CAPTCHA)的诞生本身是为了自动区分 自然人 和 机器人 的一套公开方法, 但是近几年的人工智能技术的发展,传统的字符验证已经形同虚设. 所以,大家一方面研究和学习此代码时,另外一方面也要警惕自己的互联网系统的web安全问题. Keywords: 人工智能,Python,字符验证码,CAPTCHA,识别,tensorflow,CNN,深度学习 2   Introduction 全自动区

基本类型:整型与字符型

一.整型int 1.1 概述 整数类型用来表示不同的取值范围和正负值,含义和数学一样,整数是没有小数部分的值: 区分正负的类型,称为有符类型(signed),无正负的类型(只有正值),称为无符类型. (unsigned):当声明某变量类型为无符号类型时,需要在类型声明前显示使用unsigned: 1.2 int类型 short int 类型:简写short,C规定占用的空间不能多于int long int 类型: 简写 long ,占用的空间可能比int多: long long int 类型:

C语言---整型字符串转换

C语言提供了几个标准库函数,能够将随意类型(整型.长整型.浮点型等)的数字转换为字符串.下面是用itoa()函数将整数转 换为字符串的一个样例: # include <stdio.h>    # include <stdlib.h> void main (void)    {    int num = 100;    char str[25];    itoa(num, str, 10);    printf("The number ’num’ is %d and the

自动类型转换、强制类型转换、作用域、整型表数范围

一.变量的作用域 测试代码: public class Test1 { private static int value = 1; // 全局变量 private static int temp = 0; // 全局变量 public static void main(String[] args) { int value = 2; // 局域变量覆盖全局变量 System.out.println(value); // 输出的是局域变量,全局变量被屏蔽 System.out.println(tem