C、C++

【C语言】数据类型-002

2019-10-01  本文已影响0人  CodeDove

第二章 数据类型

2.1 常量与变量


2.1.1 关键字

C的关键字

2.1.2 数据类型

数据类型的作用:编译器预算对象(变量)分配的内存空间大小。

数据类型

2.1.3 常量

常量:

常量类型 具体实例
整型常量 100,200,-100,0
实型常量 3.14 , 0.125,-3.123
字符型常量 ‘a’,‘b’,‘1’,‘\n’
字符串常量 “a”,“ab”,“12356”

2.1.4 变量

1.变量
变量:

标识符命名规则:

变量特点:

2.声明和定义区别

#include <stdio.h>

int main()
{
    //extern 关键字只做声明,不能做任何定义,后面还会学习,这里先了解
    //声明一个变量a,a在这里没有建立存储空间
    extern int a;
    a = 10; //err, 没有空间,就不可以赋值

    int b = 10; //定义一个变量b,b的类型为int,b赋值为10

    return 0;
}

从广义的角度来讲声明中包含着定义,即定义是声明的一个特例,所以并非所有的声明都是定义:

一般的情况下,把建立存储空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”。

2.1.5 使用示例

#include <stdio.h>
#define MAX 10 //声明了一个常量,名字叫MAX,值是10,常量的值一旦初始化不可改

int main()
{
    int a;  //定义了一个变量,其类型为int,名字叫a

    const int b = 10; //定义一个const常量,名为叫b,值为10
    //b = 11; //err,常量的值不能改变

    //MAX = 100;    //err,常量的值不能改变

    a = MAX;//将abc的值设置为MAX的值
    a = 123;

    printf("%d\n", a); //打印变量a的值

    return 0;
}

2.2 进制



进制也就是进位制,是人们规定的一种进位方法。 对于任何一种进制—X进制,就表示某一位置上的数运算时是逢X进一位。 十进制是逢十进一,十六进制是逢十六进一,二进制就是逢二进一,以此类推,x进制就是逢x进位。
十进制 二进制 八进制 十六进制
0 0 0 0
1 1 1 1
2 10 2 2
3 11 3 3
4 100 4 4
5 101 5 5
6 110 6 6
7 111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
16 10000 20 10

2.2.1 二进制

二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”。

当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的

术语 含义
bit(比特) 一个二进制代表一位,一个位只能表示0或1两种状态。数据传输是习惯以“位”(bit)为单位。
Byte(字节) 一个字节为8个二进制,称为8位,计算机中存储的最小单位是字节。数据存储是习惯以“字节”(Byte)为单位。
WORD(双字节) 2个字节,16位
DWORD 两个WORD,4个字节,32位
1b 1bit,1位
1B 1Byte,1字节,8位
1k,1K 1024
1M(1兆) 1024k, 1024*1024
1G 1024M
1T 1024G
1Kb(千位) 1024bit,1024位
1KB(千字节) 1024Byte,1024字节
1Mb(兆位) 1024Kb = 1024 * 1024bit
1MB(兆字节) 1024KB = 1024 * 1024Byte

十进制转化二进制的方法: 用十进制数除以2,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果。

在这里插入图片描述
十进制的小数转换成二进制: 小数部分和2相乘,取整数,不足1取0,每次相乘都是小数部分,顺序看取整后的数就是转化后的结果。
在这里插入图片描述

2.2.2 八进制

八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1。一些编程语言中常常以数字0开始表明该数字是八进制。

八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中。

在这里插入图片描述
十进制转化八进制的方法:
用十进制数除以8,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果。
在这里插入图片描述

2.2.3 十六进制

十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-9对应0-9,A-F对应10-15。

十六进制的数和二进制数可以按位对应(十六进制一位对应二进制四位),因此常应用在计算机语言中。

在这里插入图片描述
十进制转化十六进制的方法:
用十进制数除以16,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果。
在这里插入图片描述

2.2.4 C语言如何表示相应进制数

进制 具体示例
十进制 以正常数字1-9开头,如123
八进制 以数字0开头,如0123
十六进制 以0x开头,如0x123
二进制 C语言不能直接书写二进制数
#include <stdio.h>

int main()
{
    int a = 123;        //十进制方式赋值
    int b = 0123;       //八进制方式赋值, 以数字0开头
    int c = 0xABC;  //十六进制方式赋值

    //如果在printf中输出一个十进制数那么用%d,八进制用%o,十六进制是%x
    printf("十进制:%d\n",a );
    printf("八进制:%o\n", b);  //%o,为字母o,不是数字
    printf("十六进制:%x\n", c);

    return 0;
}

2.3 计算机内存数值存储方式


2.3.1 原码

一个数的原码(原始的二进制码)有如下特点:

下面数值以1字节的大小描述:

十进制数 原码
+15 0000 1111
-15 1000 1111
+0 0000 0000
-0 1000 0000

原码表示法简单易懂,与带符号数本身转换方便,只要符号还原即可,但当两个正数相减或不同符号数相加时,必须比较两个数哪个绝对值大,才能决定谁减谁,才能确定结果是正还是负,所以原码不便于加减运算。

2.3.2 反码

十进制数 反码
+15 0000 1111
-15 1111 0000
+0 0000 0000
-0 1111 1111

反码运算也不方便,通常用来作为求补码的中间过渡。

2.3.3 补码

在计算机系统中,数值一律用补码来存储。

补码特点:

十进制数 补码
+15 0000 1111
-15 1111 0001
+0 0000 0000
-0 0000 0000
#include <stdio.h>

int main()
{
    int  a = -15;

    printf("%x\n", a);
    //结果为 fffffff1
    //fffffff1对应的二进制:1111 1111 1111 1111 1111 1111 1111 0001
    //符号位不变,其它取反:1000 0000 0000 0000 0000 0000 0000 1110
    //上面加1:1000 0000 0000 0000 0000 0000 0000 1111  最高位1代表负数,就是-15

    return 0;
}

2.3.4 补码的意义

示例1:用8位二进制数分别表示+0和-0

十进制数 原码
+0 0000 0000
-0 1000 0000
十进制数 反码
+0 0000 0000
-0 1111 1111

不管以原码方式存储,还是以反码方式存储,0也有两种表示形式。为什么同样一个0有两种不同的表示方法呢?

但是如果以补码方式存储,补码统一了零的编码:

十进制数 补码
+0 0000 0000
-0 10000 0000由于只用8位描述,最高位1丢弃,变为0000 0000

示例2:计算9-6的结果
以原码方式相加:

十进制数 原码
9 0000 1001
-6 1000 0110
在这里插入图片描述

结果为-15,不正确。

以补码方式相加:

十进制数 补码
9 0000 1001
-6 1111 1010
在这里插入图片描述

最高位的1溢出,剩余8位二进制表示的是3,正确。

在计算机系统中,数值一律用补码来存储,主要原因是:

2.4 sizeof关键字


#include <stdio.h>

int main()
{
    int a;
    int b = sizeof(a);//sizeof得到指定值占用内存的大小,单位:字节
    printf("b = %d\n", b);

    size_t c = sizeof(a);
    printf("c = %u\n", c);//用无符号数的方式输出c的值

    return 0;
}

2.5整型:int


2.5.1 整型变量的定义和输出

打印格式 含义
%d 输出一个有符号的10进制int类型
%o(字母o) 输出8进制的int类型
%x 输出16进制的int类型,字母以小写输出
%X 输出16进制的int类型,字母以大写写输出
%u 输出一个10进制的无符号数
#include <stdio.h>

int main()
{
    int a = 123;    //定义变量a,以10进制方式赋值为123
    int b = 0567;   //定义变量b,以8进制方式赋值为0567
    int c = 0xabc;  //定义变量c,以16进制方式赋值为0xabc

    printf("a = %d\n", a);
    printf("8进制:b = %o\n", b);
    printf("10进制:b = %d\n", b);
    printf("16进制:c = %x\n", c);
    printf("16进制:c = %X\n", c);
    printf("10进制:c = %d\n", c);

    unsigned int d = 0xffffffff;            //定义无符号int变量d,以16进制方式赋值
    printf("有符号方式打印:d = %d\n", d);  // d=-1
    printf("无符号方式打印:d = %u\n", d);  // d=4294967295
    return 0;
}

2.5.2 整型变量的输入

#include <stdio.h>

int main()
{
    int a;
    printf("请输入a的值:");

    //不要加“\n”
    scanf("%d", &a);

    printf("a = %d\n", a); //打印a的值

    return 0;
}

2.5.3 short、int、long、long long

数据类型 占用空间
short(短整型) 2字节
int(整型) 4字节
long(长整形) Windows为4字节,Linux为4字节(32位),8字节(64位)
long long(长长整形) 8字节

注意:

整型常量 所需类型
10 代表int类型
10l, 10L 代表long类型
10ll, 10LL 代表long long类型
10u, 10U 代表unsigned int类型
10ul, 10UL 代表unsigned long类型
10ull, 10ULL 代表unsigned long long类型
打印格式 含义
%hd 输出short类型
%d 输出int类型
%l 输出long类型
%ll 输出long long类型
%hu 输出unsigned short类型
%u 输出unsigned int类型
%lu 输出unsigned long类型
%llu 输出unsigned long long类型
#include <stdio.h>

int main()
{
    short a = 10;
    int b = 10;
    long c = 10l; //或者10L
    long long d = 10ll; //或者10LL

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

    printf("short a = %hd\n", a);
    printf("int b = %d\n", b);
    printf("long c = %ld\n", c);
    printf("long long d = %lld\n", d);

    unsigned short a2 = 20u;
    unsigned int b2 = 20u;
    unsigned long c2= 20ul; 
    unsigned long long d2 = 20ull; 

    printf("unsigned short a = %hu\n", a2);
    printf("unsigned int b = %u\n", b2);
    printf("unsigned long c = %lu\n", c2);
    printf("unsigned long long d = %llu\n", d2);

    return 0;
}

2.5.4 有符号数和无符号数区别

1.有符号数
有符号数是最高位为符号位,0代表正数,1代表负数。

在这里插入图片描述
#include <stdio.h>

int main()
{
    signed int a = -1089474374; //定义有符号整型变量a
    printf("%X\n", a); //结果为 BF0FF0BA

    //B       F      0        F       F     0        B        A
    //1011 1111 0000 1111 1111 0000 1011 1010

    return 0;
}

2.无符号数
无符号数最高位不是符号位,而就是数的一部分,无符号数不可能是负数。

在这里插入图片描述
#include <stdio.h>

int main()
{
   unsigned int a = 3236958022; //定义无符号整型变量a
   printf("%X\n", a); //结果为 C0F00F46

   return 0;
}

当我们写程序要处理一个不可能出现负值的时候,一般用无符号数,这样可以增大数的表达最大值。

3.有符号和无符号整型取值范围

数据类型 占用空间 取值范围
short 2字节 -32768 到 32767 (-215 ~ 215-1)
int 4字节 -2147483648 到 2147483647 (-231 ~ 231-1)
long 4字节 -2147483648 到 2147483647 (-231 ~ 231-1)
unsigned short 2字节 0 到 65535 (0 ~ 216-1)
unsigned int 4字节 0 到 4294967295 (0 ~ 232-1)
unsigned long 4字节 0 到 4294967295 (0 ~ 232-1)
在这里插入图片描述

2.6字符型:char


2.6.1 字符变量的定义和输出

字符型变量用于存储一个单一字符,在 C 语言中用 char 表示,其中每个字符变量都会占用 1 个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号(' ')把字符括起来。

字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中。char的本质就是一个1字节大小的整型

#include <stdio.h>

int main()
{
    char ch = 'a';
    printf("sizeof(ch) = %u\n", sizeof(ch));

    printf("ch[%%c] = %c\n", ch); //打印字符
    printf("ch[%%d] = %d\n", ch); //打印‘a’ ASCII的值

    char A = 'A';
    char a = 'a';
    printf("a = %d\n", a);      //97
    printf("A = %d\n", A);  //65

    printf("A = %c\n", 'a' - 32); //小写a转大写A
    printf("a = %c\n", 'A' + 32); //大写A转小写a

    ch = ' ';
    printf("空字符:%d\n", ch); //空字符ASCII的值为32
    printf("A = %c\n", 'a' - ' '); //小写a转大写A
    printf("a = %c\n", 'A' + ' '); //大写A转小写a

    return 0;
}

2.6.2 字符变量的输入

#include <stdio.h>

int main()
{
    char ch;
    printf("请输入ch的值:");

    //不要加“\n”
    scanf("%c", &ch);
    printf("ch = %c\n", ch); //打印ch的字符

    return 0;
}

2.6.2 ASCII对照表

ASCII值 控制字符 ASCII值 字符 ASCII值 字符 ASCII值 字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 ! 65 A 97 a
2 STX 34 " 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 I
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL

ASCII 码大致由以下两部分组成:

2.6.3 转义字符

转义字符 含义 ASCII码值(十进制)
\a 警报 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\ 代表一个反斜线字符"" 092
' 代表一个单引号(撇号)字符 039
" 代表一个双引号字符 034
? 代表一个问号 063
\0 数字0 000
\ddd 8进制转义字符,d范围0~7 3位8进制
\xhh 16进制转义字符,h范围09,af,A~F 3位16进制

注意:红色字体标注的为不可打印字符

#include <stdio.h>

int main()
{
    printf("abc");
    printf("\refg\n"); //\r切换到句首, \n为换行键

    printf("abc");
    printf("\befg\n");//\b为退格键, \n为换行键

    printf("%d\n", '\123');// '\123'为8进制转义字符,0123对应10进制数为83
    printf("%d\n", '\x23');// '\x23'为16进制转义字符,0x23对应10进制数为35

    return 0;
}

2.6.4 数值溢出

当超过一个数据类型能够存放最大的范围时,数值会溢出。

有符号位最高位溢出的区别: 符号位溢出会导致数的正负发生改变,但最高位的溢出会导致最高位丢失。

数据类型 占用空间 取值范围
char 1字节 -128到 127(-27 ~ 27-1)
unsigned char 1字节 0 到 255(0 ~ 28-1)
在这里插入图片描述
#include <stdio.h>

int main()
{
    char ch;

    //符号位溢出会导致数的正负发生改变
    ch = 0x7f + 2; //127+2
    printf("%d\n", ch);
    //  0111 1111
    //+2后 1000 0001,这是负数补码,其原码为 1111 1111,结果为-127

    //最高位的溢出会导致最高位丢失
    unsigned char ch2;
    ch2 = 0xff+1; //255+1
    printf("%u\n", ch2);
    //    1111 1111
    //+1后 10000 0000, char只有8位最高位的溢出,结果为0000 0000,十进制为0

    ch2 = 0xff + 2; //255+1
    printf("%u\n", ch2);
    //    1111 1111
    //+1后 10000 0001, char只有8位最高位的溢出,结果为0000 0001,十进制为1

    return 0;
}

2.7实型(浮点型):float、double


实型变量也可以称为浮点型变量,浮点型变量是用来存储小数数值的。在C语言中, 浮点型变量分为两种: 单精度浮点数(float)、 双精度浮点数(double), 但是double型变量所表示的浮点数比 float 型变量更精确。

数据类型 占用空间 有效数字范围
float 4字节 7位有效数字
double 8字节 15~16位有效数字

由于浮点型变量是由有限的存储单元组成的,因此只能提供有限的有效数字。在有效位以外的数字将被舍去,这样可能会产生一些误差。

不以f结尾的常量是double类型,以f结尾的常量(如3.14f)是float类型。

#include <stdio.h>

int main()
{
    //传统方式赋值
    float a = 3.14f; //或3.14F
    double b = 3.14;

    printf("a = %f\n", a);
    printf("b = %lf\n", b);

    //科学法赋值
    a = 3.2e3f; //3.2*1000 = 32000,e可以写E
    printf("a1 = %f\n", a);

    a = 100e-3f; //100*0.001 = 0.1
    printf("a2 = %f\n", a);

    a = 3.1415926f;
    printf("a3 = %f\n", a); //结果为3.141593

    return 0;
}

2.8类型限定符

限定符 含义
extern 声明一个变量,extern声明的变量没有建立存储空间。`extern int a;
const 定义一个常量,常量的值不能修改。const int a = 10;
volatile 防止编译器优化代码
register 定义寄存器变量,提高效率。register是建议型的指令,而不是命令型的指令,如果CPU有空闲寄存器,那么register就生效,如果没有空闲寄存器,那么register无效。

2.9字符串格式化输出和输入


2.9.1 字符串常量

字符串常量与字符常量的不同:

在这里插入图片描述
每个字符串的结尾,编译器会自动的添加一个结束标志位'\0',即 "a" 包含两个字符'a'和’\0’。

2.9.2 printf函数和putchar函数

printf是输出一个字符串,putchar输出一个char。

printf格式字符:

打印格式 对应数据类型 含义
%d int 接受整数值并将它表示为有符号的十进制整数
%hd short int 短整数
%hu unsigned short 无符号短整数
%o unsigned int 无符号8进制整数
%u unsigned int 无符号10进制整数
%x,%X unsigned int 无符号16进制整数,x对应的是abcdef,X对应的是ABCDEF
%f float 单精度浮点数
%lf double 双精度浮点数
%e,%E double 科学计数法表示的数,此处"e"的大小写代表在输出时用的"e"的大小写
%c char 字符型。可以把输入的数字按照ASCII码相应转换为对应的字符
%s char * 字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符)
%p void * 以16进制形式输出指针
%% % 输出一个百分号

printf附加格式:

字符 含义
l(字母l) 附加在d,u,x,o前面,表示长整数
- 左对齐
m(代表一个整数) 数据最小宽度
0(数字0) 将输出的前面补上0直到占满指定列宽为止不可以搭配使用-
m.n(代表一个整数) m指域宽,即对应的输出项在输出设备上所占的字符数。n指精度,用于说明输出的实型数的小数位数。对数值型的来说,未指定n时,隐含的精度为n=6位。
#include <stdio.h>
int main()
{
    int a = 100;
    printf("a = %d\n", a);//格式化输出一个字符串
    printf("%p\n", &a);//输出变量a在内存中的地址编号
    printf("%%d\n");

    char c = 'a';
    putchar(c);//putchar只有一个参数,就是要输出的char
    long a2 = 100;
    printf("%ld, %lx, %lo\n", a2, a2, a2);

    long long a3 = 1000;
    printf("%lld, %llx, %llo\n", a3, a3, a3);

    int abc = 10;
    printf("abc = '%6d'\n", abc);
    printf("abc = '%-6d'\n", abc);
    printf("abc = '%06d'\n", abc);
    printf("abc = '%-06d'\n", abc);

    double d = 12.3;
    printf("d = \' %-10.3lf \'\n", d);

    return 0;
}

2.9.3 scanf函数与getchar函数

#include <stdio.h>

int main()
{
    char ch1;
    char ch2;
    char ch3;
    int a;
    int b;

    printf("请输入ch1的字符:");
    ch1 = getchar();
    printf("ch1 = %c\n", ch1);

    getchar(); //测试此处getchar()的作用

    printf("请输入ch2的字符:");
    ch2 = getchar();
    printf("\'ch2 = %ctest\'\n", ch2);

    getchar(); //测试此处getchar()的作用
    printf("请输入ch3的字符:");
    scanf("%c", &ch3);//这里第二个参数一定是变量的地址,而不是变量名
    printf("ch3 = %c\n", ch3);

    printf("请输入a的值:");
    scanf("%d", &a);
    printf("a = %d\n", a);

    printf("请输入b的值:");
    scanf("%d", &b);
    printf("b = %d\n", b);

    return 0;
}

上一篇下一篇

猜你喜欢

热点阅读