1-数据类型

189 阅读14分钟

使用数据的不同类型的目的:合理利用空间

计算机存储的是二进制,是一位二进制只能存放0或1,内存:1bit

1字节 == 8b(八位二进制),范围:0000 0000 ~1111 1111

4B等于4个字节

知识点一:常用关键字

------------------------------------在32位平台下---------------------------------------

关键字类型所占的空间
char字符串类型占1字节空间(8位二进制位)
short短整型占2字节空间(16位二进制位)
int整型占4个字节空间(32位二进制)
long长整型占4个字节空间(32位二进制)(在64为平台下占8个字节)
long long长长整型占8字节
float单精度浮点数占4个字节空间(32为二进制)(6-7位有效位,指数-37到38)
double双精度浮点数占8个字节空间(64为二进制)(15-16位有效位,指数-307到308)

字符型

#include<stdio.h>	//输出函数等需要的头文件
int main()
{
    char a = 'aaaaa';   //定义字符  //字符单引号,字符串双引号,字符串需要借助数组实现
    printf("%d\n",a);   //字符%d输出,按照ASCII码表输入对应字符整数
    printf("%c\n",a);   //字符%c输出,则输出字符,%s,输入字符串
    return 0;
}

整型

#include<stdio.h>
int main()
{
    int a = 123;	//定义整型
    short int b = 456;	//定义短整型
    long c = 789;		//定义长整型
    long long d = 1243543511111111;	//定义长长整型
    printf("%d,%hd,%lu,%lld",a,b,c,d);	//输出数据,123,456,789,1243543511111111
    return 0;
}

实型(浮点型)

赋值语句中若涉及到浮点数时注意两边类型尽量保持一致

浮点数赋值,若赋值右边没有加 f 默认是 double 类型(占8个字节)

指数形式:123e3(123*10的三次方)

#include<stdio.h>
int main(int argc,char *argv[])
{
    //赋值语句的 = 两边的类型尽量保持一致
    float f = 3.14f;
    double d = 3.14;
    printf("sizeof(3.14) = %d\n",sizeof(3.14));		//8
    //不以f结尾的 实型常量 为double类型
    printf("sizeof(3.14) = %d\n",sizeof(3.14f));	//4
    //以f结尾的 实型常量 为float类型
    printf("f = %f\n",f);
    printf("d = %lf\n",d);
    scanf("%f",&f);
    scanf("%lf",&d);
    return 0;
}
#include<stdio.h>
int main()
{
    float a = 3.14;  //定义float类型
    double b = 4.311111123456789;   //定义double类型
    //在输出时%f可以输出float和double,但scanf输入时不能通用
    printf("%f,%f\n",a,b);  //3.140000,4.311111
    //如果输出位数较多,得限制位数才可以输出完整
    printf("%.6f,%.15lf",a,b);   //3.140000,4.311111123456789

    //如果越界,越界的数字是随机数
    return 0;
}

测试类型所占空间

sizeof:测试类型的长度(所占的空间)

#include<stdio.h>	//输出函数等需要的头文件
int main(int argc,char *argv[])
{
    printf("sizeof(int) = %d\n",sizeof(int));	//4
    printf("sizeof(float) = %d\n",sizeof(float));	//4
    printf("sizeof(doublt) = %d\n",sizeof(double));	//8
    printf("sizeof(long) = %d\n",sizeof(long));		//4
    printf("sizeof(short) = %d\n",sizeof(short));	//2
    printf("sizeof(char) = %d\n",sizeof(char));		//1
    return 0;
}

布尔型

#include<stdio.h>	//输出函数等需要的头文件
#include<stdbool.h>	//布尔类型头文件
int main()
{
    bool a = 1;	//定义布尔类型
    printf("%d\n",a);	//1
    return 0;
}

知识点二:unsigned 和 signed

1、无符号数:unsigned

数据没有符号位,自身所有二进制位都是数据位

例:unsigned char 0000 0000 ~ 1111 1111

2、有符号数:signed(默认省略)

    二进制最高位为 1 表示负数,最高位为 0 表示正数,其他位为数据位

    负数:1xxx xxxx 正数:0xxx xxxx(x:0或1)

#include<stdio.h>
int main(int argc,char *argv[])
{
    //定义一个有符号int
    //signed int num1 = 10;
    int num2 = 10;	//有符号(signed)默认省略
    
    //unsigned 表示无符号数 不能省略
    unsigned num3 = 10;
    return 0;
}

知识点三:结构体 struct 和 共用体 union

1、struct:结构体中成员拥有独立空间

struct data1
{
    char a;
    int b;
    shuot c;
};
a,b,c就是结构体dat1中的成员

2、union:共用体中成员共享同一部分空间

union data2
{
    char a;
    short b;
    int c;
};

知识点四:enum 和 void

1、enum:枚举

将变量要赋值的值一一列举出来

enum BOOL{false,ture};
//括号里面的是可以赋给变量的值,赋的值只能括号里面有的
enum BOOL bool = false

2、void:无类型

不能用void定义变量

知识点五:其他关键字

关键字含义关键字含义
auto自动类型register寄存器变量
static静态变量const只读
sizeof测类型大小typedef为已有的类型重新取别名
volatile防止编译器优化extern外部的意思,一般用于函数和全局变量的声明

1、register:寄存器变量

寄存器内存图

总结:

  1. 如果没有显示表明 register ,类似 int num,如果被高频使用系统也会放入寄存器中

  2. register int num; //显示表明将num放入寄存器

  3. 寄存器的变量不能取地址

#include<stdio.h>
int main(int argc,char *argv[])
{
    register int num = 10;
    //%p输出地址
    printf("%p\n",&num);	//错误 不能对寄存器变量取地址
    return 0;
}

2、typedef:为已有类型取别名

#include<stdio.h>
typedef int INT32;	//取别名
int main(int argc,char *argv[])
{
    int num1 = 10;
    INT32 num2 = 34;
    printf("num1 = %d\n",num1);	//20
    printf("num2 = %d\n",num2);	//34
    return 0;
}

3、volatile:防止编译器优化

作用:强制访问内存操作

这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问

volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;

volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中

优化做法(禁止):由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读

知识点六:常量与变量

1、常量

值不能被修改(但不能反过来说:值不能被修改是常量)

例:10、20、4.14、'a'、"abcd"

2、变量

  • 系统根据变量的类型开辟对应的空间,其值可以被修改

  • 变量名 代表 空间的内容

  • 操作变量 就是对 空间内容的操作

  • 变量的命名规制:由数值、字符、下划线组成但是不能以数字开头

int num = 10;	//变量名 num 代表空间内容 10,4B字节空间

知识点七:进制

进制类型及输出方法

输出时在 % 后加 # 表示输出进制的前缀

不同进制仅仅只是数据的表现形式不会修改数据本身

#include<stdio.h>
int main(int argc,char *argv[])
{
    int num = 100;
    //加个#号就是输出进制的前缀
    printf("十进制:num = %d\n",num);	//十进制输出  %d  %u  %ld  %lu
    printf("八进制:num = %#o\n",num);	//八进制输出  %o   以0开头
    printf("十六进制:num = %#x\n",num);	//十六进制输出  %x  以0x开头
    printf("十六进制:num = %#X\n",num);	//十六进制输出,但输出的十六进制字母X为大写
    return 0;
}
//十进制:num = 100
//八进制:num = 0144
//十六进制:num = 0x64

进制转换

需要分组的只有八进制和十六进制,八进制3个数字为一组,十六进制4个数字为一组

对于整数, 有四种表示方式:

    二进制:0,1 ,满 2 进 1,以 0b 或 0B 开头

    十进制:0-9 ,满 10 进 1

    八进制:0-7 ,满 8 进 1,以数字 0 开头表示

    十六进制:0-9 及 A(10) - F(15),满 16 进 1,以 0x 或 0X 开头表示。此处的 A-F 不区分大小写

方法:8421法

二进制转八进制

三位为一组,一组按1,2,4分

0 0 1 1 0 1 0 0

​ 4 2 1 4 2 1

————————————

从左往右,三位一组,第一组三位中二进制为1的相加得八进制的个位,第二组三位中二进制为1的相加得八进制的十位,如果有第三组三位数则为1相加则为八进制的百位,以此类推

第一个三位二进制,1 0 0 则 421,为1的只有4,则八进制个位数为4

第二个三位二进制,1 1 0 则 421,为1的有4 和 2,则八进制十位数为4 + 2 = 6

则八进制为:(0)64

八进制转二进制

八进制拆开单独数字,一个数字对应三位 再按1,2,4分解

64 --》分为两组(三位一组),从左到右,第一组为4,第二组为6,6又分为4 + 2,有对应数字的二进制为1,没有为0

4 2 1 4 2 1

1 1 0 1 0 0

位数不足补零 0011 0100

二进制转十进制

直接按1、2、4、8.....分,二进制为1的数字相加

0 0 0 1 0 1 0 1

​ 16 8 4 2 1

————————————

16+4+1 = 21

十进制转二进制

十进制拆分,1,2,4,8........组合的数,无需分组

21 = 16 + 4 + 1

16 8 4 2 1

——————

1 0 1 0 1 位数不足补零,0001 0101

二进制转十六进制

四位为一组,一组按1,2,4,8分

0 0 1 1 0 1 0 0

8 4 2 1 8 4 2 1

————————

从左往右,四位一组,第一组四位中二进制为1的相加得十六进制的个位,第二组四位中二进制为1的相加得十六进制的十位,第三组四位中二进制为1的相加得十六进制的百位,以此类推

第一个四位二进制,0 1 0 0 则 8421,为1的只有4,则八进制个位数为4

第二个四位二进制,0 0 1 1 则 8421,为1的有1 和 2,则八进制十位数为1 + 2 = 3

则十六进制为:0x34

十六进制转二进制

十六进制数分开单个数字,一个数字对应四位,并拆分 1,2,4,8....数组成

0x2A =》分为两组(四位一组),从左到右,第一组为A,A又分为8 + 2,第二组为2,有对应数字的二进制为1,没有为0

8 4 2 1 8 4 2 1

————————————————

0 0 1 0 1 0 1 0

八进制转十进制

八转二,二转十

十进制转八进制

十转二,二转八

八进制转十六进制

八转二,二转十六

十六进制转八进制

十六转二,二转八

十进制转十六进制

十转二,二转十六

十六进制转十进制

十六转二,二转十

知识点八:(整型变量操作)取值、赋值

void test04()
{
    //局部变量不初始化 内容随机
    //int num;
    int data = 0;
    int num = 0;
    printf("num = %d\n",num);	//读 取值,0

    num = 100;	//写 赋值
    printf("num = %d\n",num);	//100

    data = num;	//num读 data写
    printf("data = %d\n",data);	//100

    //获取键盘输入
    printf("请输入一个int数据:");
    scanf("%d", &data);		//&data 代表是data对应空间的起始地址
    printf("data = %d\n",data);

}

知识点九:数据输出

符号含义
%d十进制有符号整数输出
%u十进制无符号整数输出
%ld有符号长整型输出
%lu无符号long数据输出
%hd/%hu有/无符号short数据输出
%o以八进制表示的整数输出
%x以十六进制表示的整数输出
%ffloat型浮点数输出
%lfdouble型浮点数输出
%e指数形式的浮点数输出
%c单个字符输出
%s字符串输出
%p指针的值输出

输出的格式

    %3d          %03d          %-3d          %5.2f

    %3d:要求宽度为3位,如果不足3位,前面空格补齐,如果足够3位,此语句无效

    %03d:要求宽度为3位,如果不足3位,前面0补齐,如果足够3位,此语句无效

    %-3d:要求宽度为3位,如果不足3位,后面空格补齐,如果足够3位,此语句无效

    %5.2f:总宽度为5,.2表示:小数位保留2位

    但不能写 %-03d

int main(int argc,char *argv[])
{
    printf("##############\n");
    //%5d 表示占5个终端位宽 右对齐
    printf("##%5d##\n",123);	//###  123###

    //%‐5d 表示占5个终端位宽 左对齐
    printf("##%‐5d##\n",123);	//###123  ###

    //%05d 表示占5个终端位宽 右对齐 不足补0
    printf("##%05d##\n",123);	//###00123###

    //千万不能写 %‐05d
    //printf("##%‐05d##\n",123);

    //%5.2f 5表示总位宽为5 .2表示小数位保留2位
    printf("##%5.2f##\n", 3.14159f);	//### 3.14###
}

实型 常量

void test06()
{
    //赋值语句 = 两边的类型 尽量保证一致
    float f = 3.14f;//有没有问题
    double d = 3.14;

    //不以f结尾的 实型常量 为double类型
    printf("sizeof(3.14) =%d\n",sizeof(3.14));	//8

    //以f结尾的 实型常量 为float类型
    printf("sizeof(3.14f) =%d\n",sizeof(3.14f));	//4

    //%f 输出 float数据
    printf("f = %f\n",f);

    //%lf 输出 double数据
    printf("d = %lf\n", d);

    scanf("%f", &f);
    scanf("%lf", &d);
}

知识点十:字符(char)常量与变量

用 ' ' 包裹字符

%c 输出输出字符,用 %d 输出字符的ascii值

本质:在内存保存的是字符对应的ASCII码值,字符与对应的ASCII值完全等价

使用 scanf 键盘输入字符用 %c 只能提取一个字符

#include<stdio.h>
void test08()
{
    //%c 输出的字符
    //printf("%c\n",'a');

    //字符变量
    char ch = 'a';	//ch 存储的是 ‘a’的ASCII值
    printf("ch = %c\n",ch);
    //%d 输出的字符的ASCII值11 
    printf("ch = %d\n",ch);

    //'a' 单引号 表示的取 字符的ASCII
    //'a' == 97是完全等价
    ch = 97;
    printf("ch = %c\n",ch);
    //%d 输出的字符的ASCII值
    printf("ch = %d\n",ch);

    ch = ch+1;
    printf("ch = %c\n",ch);
    //%d 输出的字符的ASCII值
    printf("ch = %d\n",ch);
   
}

//字符获取键盘输入
void test09()
{
	char ch;
    printf("请输入一个字符:");
    //scanf中%c只能提取一个字符
    //scanf("%c", &ch);
    ch = getchar();	//获取一个字符

    printf("ch = %c\n",ch);	//a
    printf("ch = %d\n",ch);	//97
    return 0;
}

知识点十一:字符串

用 " " 包裹字符,默认结尾自动添加\0 结尾(占一个字节),只要遇到 \0 就结束

描述:'a'和"a"的区别

    'a'字符 占1字节,"a"字符串 占2字节(多'\0')

int main(int argc,char *argv[])
{
    //%s 就是输出字符串
    //''取的是字符的ASCII值 ""取的是字符串的首元素的地址
    //%s 从字符串的首元素 逐个字符输出 遇到'\0' (重要)
    printf("%s\n", "hello");	//hello
    //系统会在字符串末尾自动添加一个结束字符'\0'
    printf("%d\n",sizeof("hello"));	//6

    printf("%s\n","hello world");	//hello world
    printf("%s\n","hello\0world");	//hello,\0:字符串结束符
    printf("##%s##\n","\0hello\0world");	//###
}

知识点十二:转义字符

字符形式功能字符形式功能
\n回车换行\\一个反斜杠字符(\)
\t将当前位置移到下一个tab位置\'一个单引号(')
\v当前位置移到下一个垂直制表对齐点\"一个双引号(")
\r回车符\ddd三位八进制数代表一个ASCII字符
\f换页符\xhh二位十六进制代表一个ASCII字符
\b将当前位置后退一个字符\0空值,其ASCII码值为0