变量与常量数据
- 在程序中预先设定好的,没有变化的被成为常量
- 在程序运行其间,可能会被改变或被赋值的,被称为变量
例如 :
// 比如,有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