基础数据类型

数据类型

C语言必须在使用变量前确定类型并定义

基础类型

C语言基础类型表

C语言类型
整数 Char Short Int Long Long long
浮点数 Float Double Long double
逻辑 bool
指针
自定义类型

表达数的范围: char < short < int < float < double

内存占据大小: 1字节~16字节

内存中的表达式: 二进制数(补码) , 编码

输入输出

类型名称 格式化
int %d
long %ld
double %lf
unsinged %u
unsigned long long %lu

小于int的类型:char,short,int才用同一种输出格式:%d

大于int的类型:输出格式%ld

sizeof

sizeof是一个运算符,其用处是给出某个类型或变量在内存中占据的字节数

用法: sizeof(类型/变量)

sizeof不会做计算,执行sizeof(int+1.0)会输出double类型的字节数

整数

类型 字节数(1字节=8比特)
char 1
short 2
int 取决于CPU
long 取决于CPU
long long 8

整数的内部表达

比int类型小的数据表达的是寄存器中的某些位,而比int大的表达的可能是多个寄存器拼凑起来的,但是不管怎么说,计算机内部都是二进制数

补码

从不同角度看是不同的数值

补码的意义就是拿补码和原码可以加出一个溢出的0

负数的补码计算方式0 - a

另一种方式2^n -a,n是这种类型的位数

  • -1 + 1 = 0

    • 0 –> (1)00000000
    • 1 –> 00000001
  • (补码-1)11111111 + 00000001 = 100000000

    所以-1 + 1 = 00000000

  • 0 - 1 = -1

    • 0 –> (1)00000000
    • 1 –> 00000001
  • (1)00000000 - 00000001 = 11111111

    所以 0 -1 = 补码形式的11111111

整数的范围

对于一个字节(8位),可以表达的是从00000000 ~ 11111111

其中00000000 为 0

11111111 ~ 100000000 为 -1 ~ -128

00000001 ~ 01111111 为 1 ~ 127

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main() {
int i = 255;
char c = 255;
printf("i=%d,c=%d",i,c);
return 0;
}

// i=255,c=-1

由此可见,不同类型的数据的范围是不同的

类型 字节数 范围
char 1字节 -128 ~ 127
short 2字节 -32768 ~ 32767
int 取决于CPU -2^32-1 ~ 2^32-1 -1

Unsigned

主要作用是为了移位做纯二进制运算

该类型的整数不以补码形式表示负数,只有正整数和0

表达正数时会将数值扩大一倍

如果一个字面量常数想表达自己是Unsigned,可以在后面加上u或U,例如:255U

整数越界

整数是以纯二进制方式进行计算的

11111111 + 1 –> 10000000 = 0

01111111 +1 –> 10000000 = -128

10000000 -1–>01111111 = 127

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main() {
char c = 127;
unsigned char c1 = 255;
printf("c+1=%d,c-1=%d\nunsingedc+1=%d,unsignedc-1=%d",c + 1,c - 1,c1 +1, c1 -1);
return 0;
}
// c+1=128,c-1=126
// unsinged c+1=256,unsigned c-1=254

选择整数类型

  • 整数之所以有这么多种是为了更准确得表达内存,做底层程序的需要
  • 没有特殊的需求情况下选择int类型就好
  • Unsigned与否只是输出的不同,但在内部计算仍然是一样的

进制

计算机只认识2进制,其他进制的数据都会被转换成2进制

其他进制只是如何把数字表达成字符串,但与内部如何表达数字没有关系

  • 0开头的数字字面量是8进制
  • 0x开头的数字字面量是16进制
  • %o用于将8进制输出10进制,%x/X用于将16进制输出10进制
  • 16进制更适合表达2进制数据,因为4位二进制正好是一个16进制位

浮点类型

类型 字长 范围 有效数字
float 32 ±(1.20×10^-38 ~ 3.40×10^38),0,±inf(无穷大),nan(非数字) 7
double 64 ±(2.2×10^-308 ~ 1.79×10^308),0,±inf(无穷大),nan(非数字) 15

输入输出

初始化float类型的变量时,需要在其后面指定f或F后缀来表明是float类型,否则按double来表达

类型 输入 输出
float %f %f,%e/%E(科学计数法)
double %lf %f,%e/%E(科学计数法)

精度

浮点数的运算没有精度可言

在%和f之间加上.n可以指定输出小数点后n位,这样的输出结果是做4舍5入(向下取整)的

范围

当0.0作为除数时,其结果就是无限大,而整数类型的0作为除数时无法编译

  • printf输出inf 表示超过范围的浮点数:±∞无穷大
  • printf输出nan 表示不存在的浮点数
1
2
3
4
5
6
7
8
#include <stdio.h>

int main() {
printf("%f\n", 1.0 / 0.0); // inf
printf("%f\n", -1.0 / 0.0); // -inf
printf("%f\n", 0.0 / 0.0); // nan
return 0;
}

选择浮点类型

同整数类型一样,选择相对来说范围较大的一个即可

在没有特殊需求的情况下,选择使用double就好

字符

之前说过Char是一种整数,但它也是一种特殊的类型:字符

  • 用单引号表示的字符字面量:'x',1
  • ''也是一个字符
  • printf和scanf里用%c来输入和输出字符类型

字符的编码才用ASCII码当输入的是整数类型,输出格式是字符格式时,会对应ASCII码

同一个输入内容,当输出格式不同时会各自表述

1
2
3
4
5
6
7
8
#include <stdio.h>

int main() {
char i = '1';
printf("%d\n",i); // 49
printf("%c",i); // 1
return 0;
}

混合输入

当scanf里以空格分割时,输入也需要带上空格

而没有使用空格的情况下,整数后的任意输入都会被记录在后面的char类型里,包括换行符号

字符计算

字符也可以做整数的运算,当然输出的也得是字符类型

  • 一个字符加一个数字得到ASCII表中那个数之后的字符

  • 两个字符相减,则得到它们在ASCII表中的距离

  • 例如

1
2
3
char c = 'A';
c++;
printf("%c\n", c); // B

大小写转换

  • 字母在ASCII表中的排列是顺序的
  • 大写字母和小写字母是分开排列的,并不能在一起
  • a~A 可以得到两段之间的距离,于是:
    • a + 'a' - 'A'可以把一个大写字母变成小写字母
    • a + 'A'- 'a'则可以把一个小写字母变成大写字母

类型转换

自动类型转换

当运算符两边出现不一致的类型时,会自动转换成能表达范围更大的类型

  • char –> short –> int –> long –> long long

  • int –> float –> double

  • 对于printf来说,任何小于int的类型都会被转换成int,float会被转换成double

  • 但对于scanf来说,得明确类型大小,要输入short时,需要%hd

强制类型转换

当需要把一个量强制转换成另一个较小范围的类型

  • 格式(类型)值(int)2.0

  • 但是小的变量类型不能表达大的值;因为整数越界,所以(short)32768 --> -32768

  • 强制类型转换只是从变量计算出一个新的类型的值,不会改变变量,无论是值还是类型都不会被改变

优先级

强制类型转换的优先级高于四则运算

逻辑类型

bool

bool类型作为非原生类型,需要在头文件加上#include <stdbool.sh>才能使用bool,true,false

真正意义上并没有所谓bool类型,它们仍然是整数

所以输出的时候也只能是输出整数类型的bool

1
2
3
4
5
6
7
8
#include <stdio.h>
#include "stdbool.h"

int main() {
bool b = true;
printf("%d", b); // 1
return 0;
}

逻辑运算

逻辑运算是对逻辑量进行的运算,结果只有0或1

而逻辑量是关系运算或逻辑运算的结果

  • 不要将赋值,包括复合赋值组合进表达式!
  • 逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果,就不会再做右边的计算了
运算符 描述 示例 结果
! 逻辑非 !x 如果x是true则结果为false,反之如果x是false则结果为true
&& 逻辑与 x && y 如果x和y都是true,结果就是true,否则任一为false其结果就是false
|| 逻辑或 x || y 如果x和y有一个是true,结果就是true,只有两者都是false时,结果才是false
e.g

x ∈(2,5) –> x > 2 && x < 5

x ∈[3,5] –> x >= 3 && x <= 5

判断大写字母

x = 'A' && x <= 'Z'

判断小写字母

x = 'a' && x <= 'z'

优先级

这三个逻辑运算的优先级是! > && > ||

而且||&&是自左向右运算的

!error && finish || done当error不为0并且finish 或 done有一个为true,那么结果就为true,否则为false

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "stdbool.h"

int main() {
bool error = false;
bool flish = true;
bool done = true;
printf("%d",!error && flish || done); // 1
return 0;
}
优先级 运算符 结合性
1 () 从左到右
2 ! + - ++ – 从右到左(单目的+和-)
3 * / % 从左到右
4 + - 从左到右
5 < <= > >= 从左到右
6 == != 从左到右
7 && 从左到右
8 || 从左到右
9 = += -= *= /= %= 从右到左

其他

条件运算符(三目运算符)

它的作用和if是一样的,这是编程语言早期遗留下的东西,和if一样可以嵌套使用,不过写法和易懂性很差

  • 条件运算符的优先级高于赋值运算符,但是低于其他的运算符

  • 条件运算符是自右向左结合的

  • 格式:x = y * 5 > 10 ? 3 : 2其中?前面是条件,?后面是条件满足时的值,:后面是条件不满足时的值,如果把它写成if语句就是:

1
2
3
4
5
if ( y * 5 > 10 ){
x = 3;
} else {
x = 2;
}

逃逸字符(转义字符)

其作用是为了表达无法输出的控制字符或特殊字符,使用反斜杠\开头,后面跟上需要逃逸(转义)的字符,这两个字符合起来,组成了一个可以正常输出的字符

字符 别名 作用
\a 响铃符 触发蜂鸣器
\b 回车 回退一格
\t table 到下一个表格位
\n 回车换行 换行
\r 回车 回车
\“ 双引号 将”变成普通字符
\‘ 单引号 将’变成普通字符
\\ 反斜杠 输出反斜杠本身

\b

回退的含义并不是删除前一位字符,而是将\b后一位字符补进前一位

1
2
3
4
5
6
#include <stdio.h>

int main() {
printf("123\bA"); // 12A
return 0;
}

\t

table是每行固定的四个空格,只要输出的字符占据table以内的字符都是按照对齐的方式排列的

  • 一个\t可以使得输出从下一个制表位开始
  • 用\t才能使得上下两行对齐

总结

类型字节数与范围

类型 存储大小 值范围
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295
float 4 或8 字节 1.2E-38 到 3.4E+38
double 8 字节 2.3E-308 到 1.7E+308
long int 4 或 8字节
long long 8字节
long double 8 或 12 或 16字节 3.4E-4932 到 1.1E+4932

运算符优先级

类别 运算符 结合性
后缀 () [] -> . 从左到右
一元 + - ! ~ ++ - - (类型) * & sizeof 从右到左
乘除 * / % 从左到右
加减 + - 从左到右
移位 << >> 从左到右
关系 < <= > >= 从左到右
相等 == != 从左到右
位与 AND & 从左到右
位异或 XOR ^ 从左到右
位或 OR | 从左到右
逻辑与 AND && 从左到右
逻辑或 OR || 从左到右
条件 ?: 从右到左
赋值 = += -= *= /= %=>>= <<= &= ^= |= 从右到左
逗号 , 从左到右

评论