吾爱汇编

 找回密码
 立即注册

QQ登录

绑定QQ避免忘记帐号

查看: 565|回复: 2

[C/C++] 0x02 数据和基本数据类型

[复制链接]
幽灵 发表于 2023-4-23 15:06 | 显示全部楼层 |阅读模式

变量与常量数据

  • 在程序中预先设定好的,没有变化的被成为常量
  • 在程序运行其间,可能会被改变或被赋值的,被称为变量 例如 :
// 比如,有200个数字,我们需要将他们放到10个盒子里,至于哪个数字放在哪个盒子里,我们对数字取模(就是求余数),模是几,我们就放到哪个盒子里
a=1...200
b=10
a%b=盒子编号
这里,a就是变量,b就是常量,因为在整个过程中,b从来不会变化

数据类型关键字

在编程语言中,数据类型不是单一的,有些数据类型表示数字,有些数据类型表示字母等

常见C语言的数据类型关键字

最初 K&R 给出的关键字 C90 标准添加的关键字 C99 标准添加的关键字
int signed _Bool
long void _Complex
short _Imaginary
unsigned
char
float
double
  • int 关键字用来表示基本的整数型
  • long,short 和 unsigned 还有 signed 用于提供基本整数类型的变式,例如 (unsigned short int 无符号短整数,long long int 长整数,unsigned int 无符号整数 等等)
  • char 关键字用于制定字母和其它字符(#,$,%,* 等),也可以表示较小的整数
  • float、double ,long double 都表示带小数点的数
  • _Bool 表示布尔值(true 或 false)
  • _Complex_Imaginary 分别是复数和虚数

位、字节和字

  • 这三位都是描述计算机数据单元和存储单元的术语,主要指存储单元
  • 位(bit):最小存储单元, 存储 0,1
  • 字节(byte):最常用的计算机存储单位,1byte=8bit 这个几乎是所有计算机对于字节的标准定义
  • 字(word):设计计算机时给定的自然存储单位,这个从编程角度来讲没有任何意义,如果要理解,可以理解为 CPU 一次操作可以处理的二进制位数
    • 我们的64位机(CPU的数据宽度),一次操作64bit,1 word = 64bit
    • 32位机(CPU的数据宽度),一次操作32bit,1word=32bit
    • 现在的电脑,如果可以装64位及以下操作系统,那么它就是64位机,只能装32位及以下操作系统,那就是32位机,以最大的为准
    • 想要详细了解,可以看《深入理解计算机操作系统》2.1.2节

整数和浮点数

整数

  • 就是没有小数部分的数,1,-1,0都是
  • 计算机中以二进制来存储整数 比如在 8 位字节中存储 7,7的二进制是111,然后需要把前面5位用0补齐

浮点型

  • 就是数学中的小数,2.75,3.16E7,7.00,2e-8 这都是
  • e 记数法,e表示10,e后面的数表示次方,3.16E7=3.16* 10^7 (3.16乘以10的7次方) 在这里,我们说一个浮点型转二进制(十进制) 整数转二进制我们是用除法来除以2,但是在小数部分,我们用乘法来给浮点型转换成二进制
将十进制 0.25 转换为二进制
0.25 * 2 = 0.5 取整数位 0
0.5  * 2 = 1.0 取整数位 1
将所有的整数部分按照从左到右顺序排列,得到 0.01 ,这就是十进制0.25 的二进制表示

上面的例子只是一个计算的过程,并不是真正的二进制表示 这里要区分以下整数和小数 位的二进制存储顺序,整数是从右到左存储,小数部分的二进制是从左到右存储

关于浮点型的二进制存储非常复杂,需要计算,如果想了解,可以查看 国际标准IEEE754

这是浮点型存储的公式 $V=(-1)^sM2^E$

  • 这里以32位浮点型说明
  • 32位浮点型是1位符号位,8位指数位,23位尾数位(小数有效位)
  • s 表示符号位,只能0或者1
  • M 表示有效数字,大于等于1,小于2
  • $2^E$ 表示指数位,这里的E是无符号数,范围0~255
  • 二进制表示为:s+E+M
比如 9.0 如何存储
32位浮点数
最高位为符号位
中间8位为指数位
最后的23位为尾数位
9.0 转为二进制为 1001.0
转换为1.001*2^3 ,这里的3 是因为小数点往左挪了3位
按照1,8,23来存放
指数位8位,中间值127,3+127=130,转换为二进制位10000010
0 10000010 001 0000 0000 0000 0000 0000
0 符号位
1000010 这里是指数+E的中间值
001 小数部分,后面补齐足够23位

C语言基础数据类型

int类型

  • 有符号整数
  • 值必须是整数
  • 既可以是正整数,也可以是负整数或零
  • 现在的范围是 32 位,4字节

声明、初始化、赋值 int 变量


// 声明
int nums; // 可以一次声明一个变量
int wight,cows,gots; // 也可以一次声明多个变量
上面这两种声明之后 scanf() 函数来获取值或者赋值

// 赋值
cows=12; 声明后赋值

// 初始化变量
int nums =20;
int wight=10,cows=20,gots=30;
int dogs,cats=94; /*虽然有效,但是不推荐,他只初始化了dogs ,容易让人误以为cats 也是 94*/

int 类型常量

上面的创建的12,20,10,30,94 都是常量,因为只是输入了,没有对他们做改变,所以他们都算是常量

来一个实际例子打印一下整数

/* print1.c 演示printf()的特性 */
#include <stdio.h>

int main(void) // C 语言的主函数,所有C语言程序第一个先加载它
{
    int ten=10;
    int two=2;
    printf("Doing it right: ");
    printf("%d minus %d is %d\n",ten,2,ten-two);
    printf("Doing it wrong: ");
    printf("%d minus %d is %d\n",ten); // 这里遗漏两个参数
    return 0;
}
// 运行结果如下
Doing it right:10 minus 2 is 8
Doing it wrong: 10 minus 任意值 is 任意值

这里的两个任意值是因为没有给对应的参数,所以才会有任意值,这不是编译器的问题,是printf() 函数的设计问题,C 中大部分函数都需要指定具体数目的参数,只有 printf() 是不确定参数数目的

进制的显示

  • C 语言中,不同进制使用的格式化输出符是不一样
  • 十六进制使用%x 或者 %X
  • 八进制使用 %o
  • 要以前缀 0 开头显示使用 %#o
  • 要以前缀 0x 开头显示使用 %#x
  • 要以前缀 0X 开头显示使用 %#X 代码演示:
#include <stdio.h>

int main(void)
{
    int x = 100;
    printf("dec = %d; octal = %O; hex = %x; Hex = %X\n",x,x,x,x);
    printf("dec = %d; octal = %#O; hex = %#x; Hex = %#X\n",x,x,x,x);
    return 0;
}
编译运行结果:
dec = 100; octal = %O; hex = 64; Hex = 64
dec = 100; octal = %#O; hex = 0x64; Hex = 0X64

其他整数类型

  • short int 类型 (简写为 short) 占用存储空间比 int 类型少,short 是有符号类型
  • long int 或 long 占用的存储空间可能比 int 多,适用于较大数值场合,也是有符号类型
  • long long int 或 long long (C99 标准加入) 占用存储空间比 long多,适用于更大的数值场合,最少占64位,有符号
  • unsigned int 或 unsigned 无符号整数,最小值是 0 ,没有符号位
  • C 90 标准中又添加了 unsigned long int 或 unsigned long 和 unsigned int 或 unsigned short 类型
  • C 99 标准又添加了 unsigned long long int 或 unsigned long long
  • 只要是有符号类型添加关键字 signed ,羌道使用有符号类型的意图
// 变量声明
long int estine;
long johns;
short int erns;
short ribs;
unsigned int s_count;
unsigned players;
unsigned long headcount;
unsigned short yesvotes;
long long ago;

为啥使用这么多类型,因为历史原因,刚开始只有int,后来为了适应新机型,所以扩展了这么多的数据类型 总的来说都是为了适应不同的机器

整数溢出

查看原码,反码,补码 最后那里的解答

打印一下上面说到的类型

/* printf2.c 更多printf()的特性 */

#include <stdio.h>

int main(void)
{
    unsigned int un = 3000000000; /* int 为32位和short为16位的系统*/
    short end = 200;

    long big = 65537;

    long long verbig = 12345678908642;

    printf("un = %u and not %d\n", un, un);

    printf("end = %hd and %d\n", end, end);

    printf("big = %ld and not %hd\n", big, big);

    printf("verybig= %lld and not %ld\n", verybig, verybig);

    return 0;
}

在特定的系统中输出如下(输出的结果可能不同):
un = 3000000000 and not -1294967296
end = 200 and 200
big = 65537 and not 1
verybig= 12345678908642 and not 1942899938

char 类型

  • 用于存储字符(字母,标点符号)
  • char是整数类型,实际上存储的是整数(ASCII编码)
  • 占1 字节
  • 有的编译器把 char 实现为有符号类型,有的是无符号类型,具体查询对应的编译器手册
  • C90 标准,C语言可以在 char 前使用 signed 或 unsigned,用来区别有符号和无符号类型

类型声明、赋值、初始化

// 声明
char response;
char itable,latan; // 连续声明

// 字符常量和初始化
char grade = 'A'; // C语言中,用单引号阔气来的单个字符被称为字符常量

char grade = 65; // 也没问题,但是不推荐,因为不直管,打印出来是A 

char grade = 'FATE' // 这个初始化,最后只能输出E,因为4个独立的8位ASCII码存储在一个32位存储单元中,但是赋值给 grade,他只保留最后8位

非打印字符

  • 单引号只适用于字母和标点符号
  • 但是ASCII字符中还有很多打印不出来的,比如 换行,退格等
  • \\:表示反斜杠字符(\)
  • \':表示单引号字符(')
  • \":表示双引号字符(")
  • \t:表示制表符(Tab)
  • \r:表示回车符(Carriage Return)
  • \n:表示换行符(Line Feed)
  • \b:表示退格符(Backspace)
  • \f:表示换页符(Form Feed)
  • \v:表示垂直制表符(Vertical Tab)
  • \a :C90新增报警字符,能不能看到或听到报警,看硬件是否支持
/* charcode.c 显示字符的代码 */

#include <stdio.h>

int main(void)
{
    char ch;
    printf("Please enter a character.\n");
    scanf("%c",&ch); /* 用户输入字符 */
    printf("The code for %c is %d.\n",ch,ch);
    return 0;
}
结果:
Please enter a character.
// 输入一个字符
C
The code for C is 67.

_Bool 类型

  • C99标准 添加的类型
  • 1位存储空间
  • 存储 true 和 false
  • 1为true ,0为 false

float、double 和 long double

  • 常用语数学和金融,大多数软件都是整数够用
  • 最常见的三种记数法:
    • 数字 123.35
    • 科学记数法:1.0 * 10^9
    • 指数记数法:1.0e9 就是 1.0 * 10^9
  • float 单精度,类型必须至少能表示6位有效数字(小数点后6位)
  • double 双精度,占用64位,必须至少能表示13位有效数字
  • long double ,满足比double精度更高的要求,最少和double精度相同

数据类型大小

我们使用系统提供的函数sizeof() 来查看各个数据类型的大小

/* typesize.c 打印类型大小 */

#include <stdio.h>

int main(void)
{
    /* C99和C11 为类型大小提供了 %zd 格式化输出符 */
    /* 不支持C99和C11的编译器可以用%u或%lu代替 */
    printf("Type int has a size of %zd bytes.\n",sizeof(int));
    printf("Type char has a size of %zd bytes.\n",sizeof(char));
    printf("Type long has a size of %zd bytes.\n",sizeof(long));
    printf("Type long long has a size of %zd bytes.\n",sizeof(long long));
    return 0;
}

C 各数据类型占用大小

数据类型 存储大小 最小值 最大值
char 1 字节 -128 127
unsigned char 1 字节 0 255
short 2 字节 -32,768 32,767
unsigned short 2 字节 0 65,535
int 4 字节 -2,147,483,648 2,147,483,647
unsigned int 4 字节 0 4,294,967,295
long 4 字节或 8 字节* -2,147,483,648 2,147,483,647
unsigned long 4 字节或 8 字节* 0 4,294,967,295
float 4 字节 1.175494e-38 3.402823e+38
double 8 字节 2.225074e-308 1.797693e+308
long double 16 字节 3.362103e-4932 1.189731e+4932
在不同的平台和编译器中,long 类型可能是 4 字节或 8 字节,取决于操作系统的位数和编译器的实现方式。

C 常用格式化输出符

  • %d:十进制有符号整数
  • %u:十进制无符号整数
  • %f:十进制浮点数
  • %e%E:指数表示的浮点数
  • %g%G:浮点数,自动选择 %f%e
  • %c:字符
  • %s:字符串
  • %p:指针的地址
  • %n:已打印字符数的存储地址
  • %x%X:十六进制表示的无符号整数
  • %o:八进制表示的无符号整数
  • %zd:C99标准为 sizeof() 函数添加的输出符,显示类型大小
  • %lu:在不支持C99和C11标准的编译器里使用这个或者 %u 替代 %zd

评分

参与人数 4HB +3 THX +3 收起 理由
消逝的过去 + 1
sjtkxy + 1 + 1
花盗睡鼠 + 1 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!
zxjzzh + 2 [吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守!

查看全部评分

吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
1729916784 发表于 2023-4-27 01:54 | 显示全部楼层
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
头像被屏蔽
sjtkxy 发表于 2023-6-24 04:59 | 显示全部楼层

提示: 作者被禁止或删除 内容自动屏蔽
吾爱汇编论坛-学破解,防破解!知进攻,懂防守!逆向分析,软件安全!52HB.COM
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

警告:本站严惩灌水回复,尊重自己从尊重他人开始!

1层
2层
3层

免责声明

吾爱汇编(www.52hb.com)所讨论的技术及相关工具仅限用于研究学习,皆在提高软件产品的安全性,严禁用于不良动机。任何个人、团体、组织不得将其用于非法目的,否则,一切后果自行承担。吾爱汇编不承担任何因为技术滥用所产生的连带责任。吾爱汇编内容源于网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除。如有侵权请邮件或微信与我们联系处理。

站长邮箱:SharkHeng@sina.com
站长QQ:1140549900


QQ|RSS|手机版|小黑屋|帮助|吾爱汇编 ( 京公网安备11011502005403号 , 京ICP备20003498号-6 )|网站地图

Powered by Discuz!

吾爱汇编 www.52hb.com

快速回复 返回顶部 返回列表