【新书推荐】3.3 整型

本节必须掌握的知识点:

   整型数据类型的取值范围

   示例八

   代码分析

   汇编解析

   获取数据类型的取值范围

3.3.1 整型数据类型取值范围

整型是用来表示限定范围内连续整数的数据类型。表3-1列出了C语言编译器定义的整型数据类型及其大小和取值范围。

表3-1整型数据类型

类型

存储大小

值范围

整型          int

24字节

-32768 ~32767】或

-2147483648~2147483647

短整型       short int

2字节

-32768 32767

长整型       long int

4字节

-2147483648~2147483647

无符号整型 unsigned int

24字节

0 ~65535 或【 0 ~4294967295

无符号短整型 unsigned short int

2字节

0 ~65535

无符号长整型 unsigned long int

4字节

0 ~4294967295

【注:各种数据类型的存储大小与操作系统位数有关,如下表3-2、3-3、3-4所示,分别列出了16位、32位、64位操作系统中基本类型存储的字节大小】

16位操作系统】

类型

存储大小

值范围

整型          int

2字节

-32768 ~32767

短整型       short int

2字节

-32768 32767

长整型       long int

4字节

-2147483648~2147483647

无符号整型 unsigned int

2

0 ~65535

无符号短整型 unsigned short int

2字节

0 ~65535

无符号长整型 unsigned long int

4字节

0 ~4294967295

                            

表3-2 16位操作系统整型数据类型

32位操作系统】

类型

存储大小

值范围

整型          int

4字节

-2147483648~2147483647

短整型       short int

2字节

-32768 32767

长整型       long int

4字节

-2147483648~2147483647

无符号整型 unsigned int

4字节

0 ~4294967295

无符号短整型 unsigned short int

2字节

0 ~65535

无符号长整型 unsigned long int

4字节

0 ~4294967295

表3-3 32位操作系统整型数据类型

64位操作系统

类型

存储大小

值范围

整型          int

4字节

-2147483648~2147483647

短整型       short int

2字节

-32768 32767

长整型       long int

8字节

-9223372036854775808~

9223372036854775807

long long

8字节

-9223372036854775808~

9223372036854775807

_int64

8字节

-9223372036854775808~

9223372036854775807

无符号整型 unsigned int

4字节

0 ~ 4294967295

无符号短整型 unsigned short int

2字节

0 ~ 65535

无符号长整型 unsigned long int

8字节

0 ~ 18446744073709551615

unsigned long long

8字节

0 ~ 18446744073709551615

unsigned __int64

8字节

0 ~ 18446744073709551615

                                     

表3-4 64位操作系统整型数据类型

接下来以代码+解释说明的形式详细讲述怎样使用这些数据类型,怎样检测数据类型,以及怎么判断它的取值范围。

我们以32位操作系统下的整型数据类型为例。

【整型】

“整型”从字面理解是整数类型的意思,整数类型只能存储整数,不能存储小数。整型按照存储空间的大小可以分为short类型、int类型、long类型和long long类型。如果存储的数据超出该数据类型的存储空间,则会溢出,造成数据丢失。或者编译时以错误提示的形式告知。C语言编译器在编译时会对数据类型做严格的检查,帮助程序员减少错误的发生。

如果按取值范围来划分,我们又可以把整型分为有符号整型和无符号整型。在C语言中,无符号类型表示非负整数,即大于或等于0的数;有符号类型既可以是正数也可以是负数,也可以是0,但只能是整数。

实验二十三:超出数据类型存储空间

以示例七为例,控制台窗口输入一个超出范围的整数值,如下所示:

请输入一个整型:

11111111111111111111111111111111111111111111111111111111111111111111

用户输入的内容是-1。

源程序中定义控制台输入的整数值存储在int类型的变量y中。在C语言中,如果有符号整数超出范围,将以其最大值的补码形式存储。如果无符号整数溢出,将丢弃溢出的数据位。假如存储的是一个超大值,编译器将提示错误信息。

还存在另外一种情况,假如是控制台输入一个超大值,不论是有符号整型还是无符号整型,最终存储值均为-1。

仍以示例其为例,将变量y修改为无符号整型:

unsigned int y;     //准备变量

请输入一个整型:

11111111111111111111111111111111111111111111111111111111111111111111

用户输入的内容仍然是-1。

举例

#include <stdio.h>

int main()

{

unsigned int a = 0x100000000;//丢弃最高位1

int b = 0xffffffff;      //int类型最大值0x7fffffff的补码为0x10000001

printf("a=%u, b=%d\n", a, b);

return 0;

}

运行结果:
a=0, b=-1

假设是一个超大值:

unsigned int a = 222222222222222222222222222222222222;

编译时提示:

error C2177: 常量太大

注:计算补码的方法:符号位不变,其余各位取反后加1。

3.3.2 示例八

接下来验证int、short int、long int有符号整型能储存多少字节。

示例代码八

int main(void)

{

    int i = 0;

    printf("int 存储大小 : %u byte\n", sizeof(i));//无符号整型输出

    short int  x = 0;//【可以缩写为 short x = 0;】

    printf("short 存储大小 : %u byte\n", sizeof(x));//无符号整型输出

    long int y = 0;//【可以缩写为 long y = 0;】

    printf("long 存储大小 : %lu byte\n", sizeof(y));//无符号长整型输出

    system("pause");

    return 0;

}

       ●输出结果:

       int 存储大小 : 4 byte

short 存储大小 : 2 byte

long 存储大小 : 4 byte

请按任意键继续. . .

3.3.3 代码分析

示例八输出的结果显示:

在VS编译器中,使用sizeof()运算符取出有符号整型数据长度。int存储空间大小为4字节;short 存储空间大小为2字节;long存储空间大小为4字节。

printf函数输出的格式化说明符’%u’表示无符号整型unsigned int格式,’%lu’表示long unsigned无符号长整数格式。之所以使用无符号整数格式输出,说明使用sizeof()运算符取出的数据类型的长度均为以字节为单位的正整数。

当然在这里使用’%d’有符号整数格式输出也是没有问题的,只要不超出有符号整数的数据范围即可。在很多情况下,程序员处于习惯的原因,使用有符号整数数据类型显示无符号整数,但是建议采用规范的编码格式,避免不必要的错误。

实验二十四:超出数据类型存储空间

将示例八中printf函数的格式化说明符改为’%d’,

printf("int 存储大小 : %d byte\n", sizeof(i));

printf("short 存储大小 : %d byte\n", sizeof(x));

printf("long 存储大小 : %d byte\n", sizeof(y));

按F7编译:

========= 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

然后输出结果:

int 存储大小 : 4 byte

short 存储大小 : 2 byte

long 存储大小 : 4 byte

请按任意键继续. . .

3.3.4 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data       ;全局区

i      sdword 0     ;等价于int类型

x      sword    0     ;等价于short int类型

y     sdword 0     ;等价于long int类型

.const     ;常量区

szMsg1 db "int 存储大小 : %u byte",0dh,0ah,0

szMsg2 db "short 存储大小 : %u byte",0dh,0ah,0

szMsg3 db "long 存储大小 : %lu byte",0dh,0ah,0

.code      ;代码区

start:

       push sizeof i

       push offset szMsg1     

       call printf             

       ;

       push sizeof x

       push offset szMsg2     

       call printf             

       ;

       push sizeof y

       push offset szMsg3     

       call printf             

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

int 存储大小 : 4 byte

short 存储大小 : 2 byte

long 存储大小 : 4 byte

汇编代码中,使用sizeof操作符取出变量的长度。汇编数据类型sdword等价于C语言数据类型int,sword类型等价于short int类型,sdword类型等价于long int类型。

       ■反汇编代码

        int i = 0;

00E81838  mov         dword ptr [i],0 

    printf("int 存储大小 : %u byte\n", sizeof(i));//无符号整型输出

00E8183F  push        4 

00E81841  push        offset string "int \xb4\xe6\xb4\xa2\xb4\xf3\xd0\xa1 : %u byte\n" (0E87B30h) 

00E81846  call        _printf (0E8104Bh) 

00E8184B  add         esp,8 

    short int  x = 0;//【可以缩写为 short x = 0;】

00E8184E  xor         eax,eax 

    short int  x = 0;//【可以缩写为 short x = 0;】

00E81850  mov         word ptr [x],ax 

    printf("short 存储大小 : %u byte\n", sizeof(x));//无符号整型输出

00E81854  push        2 

00E81856  push        offset string "short \xb4\xe6\xb4\xa2\xb4\xf3\xd0\xa1 : %u byte\n" (0E87B4Ch) 

00E8185B  call        _printf (0E8104Bh) 

00E81860  add         esp,8 

    long int y = 0;//【可以缩写为 long y = 0;】

00E81863  mov         dword ptr [y],0 

    printf("long 存储大小 : %lu byte\n", sizeof(y));//无符号长整型输出

00E8186A  push        4 

00E8186C  push        offset string "long \xb4\xe6\xb4\xa2\xb4\xf3\xd0\xa1 : %lu byte\n" (0E87B6Ch) 

00E81871  call        _printf (0E8104Bh) 

00E81876  add         esp,8

观察下面的反汇编语句:

    int i = 0;

mov dword ptr [i],0

short int  x = 0;//【可以缩写为 short x = 0;】

mov word ptr [x],ax

long int y = 0;//【可以缩写为 long y = 0;】

mov dword ptr [y],0

int类型对应汇编dword类型是4字节; short类型对应word类型是2字节;long类型对应dword类型是4字节。

提示

  1. 在C语言中int字长和机器字长相同;
  2. 操作系统字长和机器字长未必一致;(比如在64位系统下运行32位程序。)
  3. 编译器根据操作系统字长来规定int字长的;

在Linux系统上,int的字长与处理器的字长一致;在Windows操作系统上,操作系统的字长与处理器的字长不一定一致,编译器根据系统的字长来定义int的字长。

       4.在VS编译器中,默认缺省的数据类型为int类型,默认缺省的浮点类型是double类型。

3.3.5 获取数据类型的取值范围

实验二十五:获取有符号数据类型的取值范围

C标准库<limits.h>头文件中使用宏定义了各种数据类型的取值范围,宏定义可以直接使用,例如CHAR_BIT、INT_MIN、INT_MAX等,具体见附录D。

/*

   limits.h 头文件取数据类型取值范围

*/

#include <stdio.h>

#include <stdlib.h>

#include <limits.h>

int main(void)

{

printf("The number of bits in a byte %d\n", CHAR_BIT);//一个字节数据位数

printf("The minimum value of INT = %d\n", INT_MIN); // int 最小值

printf("The maximum value of INT = %d\n", INT_MAX); // int 最大值

printf("The minimum value of SHORT INT = %d\n", SHRT_MIN);// short 最小值

printf("The maximum value of SHORT INT = %d\n", SHRT_MAX);// short 最大值

printf("The minimum value of LONG = %ld\n", LONG_MIN); // long 最小值

printf("The maximum value of LONG = %ld\n", LONG_MAX); // long 最大值

system("pause");

return 0;

}

●输出结果:

The number of bits in a byte 8

The minimum value of INT = -2147483648

The maximum value of INT = 2147483647

The minimum value of SHORT INT = -32768

The maximum value of SHORT INT = 32767

The minimum value of LONG = -2147483648

The maximum value of LONG = 2147483647

请按任意键继续. . .

       ●查看limits.h头文件

VS中鼠标选中limits.h头文件,点击鼠标右键,选中“打开文档<limits.h>”,显示内容如下:

//

// limits.h

//

//      Copyright (c) Microsoft Corporation. All rights reserved.

//

// The C Standard Library <limits.h> header.

//

#pragma once

#define _INC_LIMITS

#include <vcruntime.h>

_CRT_BEGIN_C_HEADER

#define CHAR_BIT      8         // number of bits in a char

#define SCHAR_MIN   (-128)      // minimum signed char value

#define SCHAR_MAX     127       // maximum signed char value

#define UCHAR_MAX     0xff      // maximum unsigned char value

#ifndef _CHAR_UNSIGNED

    #define CHAR_MIN    SCHAR_MIN   // mimimum char value

    #define CHAR_MAX    SCHAR_MAX   // maximum char value

#else

    #define CHAR_MIN    0

    #define CHAR_MAX    UCHAR_MAX

#endif

#define MB_LEN_MAX    5             // max. # bytes in multibyte char

#define SHRT_MIN    (-32768)        // minimum (signed) short value

#define SHRT_MAX      32767         // maximum (signed) short value

#define USHRT_MAX     0xffff        // maximum unsigned short value

#define INT_MIN     (-2147483647 - 1) // minimum (signed) int value

#define INT_MAX       2147483647    // maximum (signed) int value

#define UINT_MAX      0xffffffff    // maximum unsigned int value

#define LONG_MIN    (-2147483647L - 1) // minimum (signed) long value

#define LONG_MAX      2147483647L   // maximum (signed) long value

#define ULONG_MAX     0xffffffffUL  // maximum unsigned long value

#define LLONG_MAX     9223372036854775807i64       // maximum signed long long int value

#define LLONG_MIN   (-9223372036854775807i64 - 1)  // minimum signed long long int value

#define ULLONG_MAX    0xffffffffffffffffui64       // maximum unsigned long long int value

#define _I8_MIN     (-127i8 - 1)    // minimum signed 8 bit value

#define _I8_MAX       127i8         // maximum signed 8 bit value

#define _UI8_MAX      0xffui8       // maximum unsigned 8 bit value

#define _I16_MIN    (-32767i16 - 1) // minimum signed 16 bit value

#define _I16_MAX      32767i16      // maximum signed 16 bit value

#define _UI16_MAX     0xffffui16    // maximum unsigned 16 bit value

#define _I32_MIN    (-2147483647i32 - 1) // minimum signed 32 bit value

#define _I32_MAX      2147483647i32 // maximum signed 32 bit value

#define _UI32_MAX     0xffffffffui32 // maximum unsigned 32 bit value

// minimum signed 64 bit value

#define _I64_MIN    (-9223372036854775807i64 - 1)

// maximum signed 64 bit value

#define _I64_MAX      9223372036854775807i64

// maximum unsigned 64 bit value

#define _UI64_MAX     0xffffffffffffffffui64

#if _INTEGRAL_MAX_BITS >= 128

    // minimum signed 128 bit value

    #define _I128_MIN   (-170141183460469231731687303715884105727i128 - 1)

    // maximum signed 128 bit value

    #define _I128_MAX     170141183460469231731687303715884105727i128

    // maximum unsigned 128 bit value

    #define _UI128_MAX    0xffffffffffffffffffffffffffffffffui128

#endif

#ifndef SIZE_MAX

    #ifdef _WIN64

        #define SIZE_MAX _UI64_MAX

    #else

        #define SIZE_MAX UINT_MAX

    #endif

#endif

#if __STDC_WANT_SECURE_LIB__

    #ifndef RSIZE_MAX

        #define RSIZE_MAX (SIZE_MAX >> 1)

    #endif

#endif

_CRT_END_C_HEADER

实验二十六:获取无符号数据类型的长度

/*

   输出无符号整型的长度

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

    unsigned int i = 0;

    unsigned short int  s = 0;//【可以缩写为unsigned short s = 0;】

    unsigned long int l = 0;//【可以缩写为 unsigned long l = 0;】

    printf("unsigned int 存储大小 : %u byte\n", sizeof(i));

    printf("unsigned short int 存储大小 : %u byte\n", sizeof(s));

    printf("unsigned long int 存储大小 : %u byte\n", sizeof(l));

    system("pause");

    return 0;

}

●输出结果:

unsigned int 存储大小 : 4 byte

unsigned short int 存储大小 : 2 byte

unsigned long int 存储大小 : 4 byte

请按任意键继续. . .

 

结论

unsigned int 存储空间大小为4字节;unsigned short int 存储空间大小为2字节;unsigned long int 存储空间大小为4字节;

unsigned int、unsigned short int、unsigned long int的 范围在这里就不做实验了,希望读者能够自己动手完成【同样使用limits.h库函数】。

【无符号整型和有符号整型的区别】

     本节只对32位操作系统下int 和 unsigned int做比较。

     int:有符号整数,占4个字节,可表示范围【-2147483648~2147483647】。

     unsigned int:无符号整数,占4个字节,可表示范围【 0 ~4294967295】。

在C语言中初始化 int i = -1;其实等价与signed int i = -1;关键字signed可以省略。因为C语言默认就是有符号类型的。

   为了说明signed和unsigned的区别,首先要搞清楚数据在内存中是如何存储的。

举例

Unsigned int i =1;变量i在内存中是 0000 0000 0000 0000 0000 0000 0000 0001存储的,由于unsigned int 是无符号整型,所以它的32位全部用来存储数据;用图表的形式表示:

32位存储数据32

int j = -1;由于int是有符号整型,所以就要考虑符号位的问题了。还有一点就是正数是以它自身形式存储的,而负数是以补码的形式存储的,参见《X86汇编基础教程》预备知识,此处不再赘述,直接写出-1原码、反码、补码。

-1的源码:   1000 0000 0000 0000 0000 0000 0000 0001

反码              1111 1111 1111 1111 1111 1111 1111 1110

补码:      1111 1111 1111 1111 1111 1111 1111 1111

            

从高位到地位    最高位为符号位,其余31位存储数据

实验二十七:获取无符号数据类型的长度

分别定义int类型变量j和unsigned int类型变量i,并给两个变量赋给相同的值-1,然后分别按照’%u’和’%d’格式输出。

/*

   输出无符号整型和有符号整数

*/

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

    unsigned int  i = 0;

    int j = -1;

    i = j;

    printf("i = %u\n", i);

    printf("j = %d\n", j);

    system("pause");

    return 0;

}

●输出结果:

i = 4294967295

j = -1

请按任意键继续. . .

控制台窗口中显示的”i = 4294967295“,这个结果怎么来的呢?

因为变量j为int有符号整数类型,值为-1,负整数以补码形式存储在内存中,-1的补码是:

变量i为unsigned int无符号整数类型,存储时编译器将-1转换为补码然后存储到内存中,无符号整数将32位全部看作是数值位,因此按照无符号整数格式输出的0xffffffff的十进制数为4294967295。

unsigned int 类型的取值范围0 ~4294967295,即0~232-1,int 类型的取值范围-231~231-1,-1是最大负整数,如下图所示:

                           

                                                图3-4 32位整数取值范围

在图3-4中,无符号数均为正数,取值范围是:【0~0xFFFFFFFF】。

有符号数正整数的范围是:【0~0x7FFFFFFF】。

有符号数负整数的范围是:【0x80000000~0xFFFFFFFF】。

接下来我们在内存中观察变量i和变量j的值:

第一步:在VSunsigned int  i = 0;一行F9下断点;

第二步:F5调试执行,在监视窗口1输入’&i’和’&j’,监视窗口显示两个变量的初始值:

第三步:F10单步执行到ystem("pause");语句,此时监视窗口按照十六进制格式显示内容如下:

       第四步:监视窗口点击鼠标右键,去掉“十六进制显示”选项,按照默认十进制格式显示内容如下:

其中已返回printf表示printf函数的返回值为7,即7个字符"j = %d\n"

以上介绍的是整型数据类型,下面介绍浮点型数据类型。

本文摘自编程达人系列教材《汇编的角度——C语言》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/427143.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

99.乐理基础-简谱的多声部

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;98.乐理基础-记号篇-装饰音记号&#xff08;六&#xff09;倚音-CSDN博客 单声部&#xff1a; 单声部可以理解成只有单一的旋律线条&#xff0c;没有其它的伴奏之类的&#xff0c;也就是说同时只能发出一个音的情况…

LoadRunner从零开始之走近LoadRunner

3.1 LoadRunner 的运行原理 安装LoadRunner 后&#xff0c;在菜单“开始” 一“MercuryLoadRunner” 中&#xff0c;你会看 到这样一组程序&#xff0c;如图 3-1 所示。 • 其中Applications 下面的Analysis、Controller 和Virtual User Generator 是我们 做性能测试最常用的…

【计算机网络】UDP协议与TCP协议

文章目录 一、端口号1.什么是端口号2.端口号范围划分3.认识知名端口号(Well-Know Port Number)4.netstat5.pidof 二、UDP协议1.UDP协议端格式2.UDP的特点3.面向数据报4.UDP的缓冲区5.UDP使用注意事项6.基于UDP的应用层协议 三、TCP协议1.TCP协议段格式1.1理解封装解包和分用1.2…

3.【SpringBoot3】文章分类接口开发

序言 在文章分类模块&#xff0c;有以下接口需要开发&#xff1a; 新增文章分类文章分类列表获取文章分类详情更新文章分类删除文章分类 数据库表字段和实体类属性&#xff1a; 在数据库表中&#xff0c;create_user 来自于 user 表中的主键 id&#xff0c;是用来记录当前文…

LTD261次升级 | 小程序支持抖音客服、支持抖音登录 • 短信发送需实名认证 • 表单提交成功收邮件提醒

1、 抖音小程序新增抖音IM客服功能&#xff1b; 2、 抖音小程序支持一键登录、支持快捷授权手机号 3、 表单新增发送邮件到提交者邮箱&#xff1b; 4、 表单支持配置不自动推送客户管理&#xff1b; 5、 短信发送需实名认证签署承诺书&#xff1b; 6、 其他已知问题修复与优化&…

别不信❗️你离数据专家只差一个CDMP证书

1⃣️为什么选择CDMP证书&#xff1f; &#x1f31f;&#x1f31f;亲爱的朋友们&#xff0c;如果你在寻找一个能让你在数据管理领域大展拳脚的证书&#xff0c;那么CDMP&#xff08;Certified Data Management Professional&#xff09;证书就是你的不二之选&#xff01;&#…

iou的cpu和gpu源码实现

本专栏主要是深度学习/自动驾驶相关的源码实现,获取全套代码请参考 简介 IoU&#xff08;Intersection over Union&#xff09;是一种测量在特定数据集中检测相应物体准确度的一个标准&#xff0c;通常用于目标检测中预测框&#xff08;bounding box&#xff09;之间准确度的…

Tomcat 优化

1、隐藏版本信息 隐藏 HTTP 头部的版本信息 # 为 Connector 添加 server 属性 vim /usr/local/tomcat/conf/server.xml <Connector port"8080" protocol"HTTP/1.1" connectionTimeout"20000" redirectPort"8443" server"w…

红日二靶场

红日二靶场 靶场的搭建配置环境 一&#xff0c;信息收集1.网段探测2.端口扫描 二&#xff0c;渗透测试1.漏洞发现2.漏洞利用1.上传木马文件2.生成哥斯拉木马文件3.连接哥斯拉4.生成msf恶意程序5.本机开启监听6.将生成的msf文件上传 3.永恒之蓝漏洞1.EarthWorm隧道搭建2.ms17-01…

MyBatis详解(1)-- ORM模型

MyBatis详解&#xff08;1&#xff09; JDBC的弊端&#xff1a; ORM 模型常见的ORM模型&#xff1a;mybatis和Hibernate的区别 ***优势&#xff1a;mybatis解决问题&#xff1a;优点&#xff1a; MyBatisMyBatis环境搭建项目架构mybatis生命周期 JDBC的弊端&#xff1a; 1.硬编…

【极数系列】Flink环境搭建(02)

【极数系列】Flink环境搭建&#xff08;02&#xff09; 引言 1.linux 直接在linux上使用jdk11flink1.18.0版本部署 2.docker 使用容器部署比较方便&#xff0c;一键启动停止&#xff0c;方便参数调整 3.windows 搭建Flink 1.18.0版本需要使用Cygwin或wsl工具模拟unix环境…

[设计模式Java实现附plantuml源码~创建型] 产品族的创建——抽象工厂模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…