优先级与结合性表格图示
不同编译器会从整体或者局部开始计算,所以会产生不同的执行效果,代码应考虑好优先性和结合性的顺序
++或--前缀与后缀注意点
++或 -- 无论前缀还是后缀都遵循优先级与结合性的规则
++或者 -- 后缀具有滞后性的特点,按照优先级和结合性先算 p++, 但由于先进行滞后性,让p先进行其他操作了,其次才进行p=p+1的操作。
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 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ` |
31 | US | 63 | ? | 95 | _ | 127 | DEL |
其中ASCII码为 0 的表示空字符,'\0' 不是空格字符,' '
其中ASCII码为10的表示转行字符,'\n'
它们都是转义字符
基础知识补充:
基本类型的范围大小
size_t 是专门为sizeof 设置的一个类型
size_t 的本质是在32位下是unsigned int
在64位下为无符号长整形类型 unsigned long 或 unsigned long long
size_t 类型的数据在打印的时候,格式应该使用%zd
int存储范围:1.11111111111111111111111——0.11111111111111111111111(-2147483648——2147483647)(-2147483648:1.00000000000000000000000(补码))
char的存储范围:1.1111111--0.1111111 (-128——127)(-128:1.0000000(补码)
short的存储范围:1.111111111111111-0.111111111111111(-32768——32767)(-32768:1.000000000000000(补码))
unsigned char:00000000-11111111(0——255)
unsigned short:0000000000000000——1111111111111111(0——65535)
类型 | 字节 |
sizeof(int) | 4 |
sizeof(char) | 1 |
sizeof(short) | 2 |
sizeof(long) | 4 |
sizeof(long long) | 8 |
sizeof(float) | 4 |
sizeof(double) | 8 |
sizeof(unsigned int) | 4 |
sizeof(unsigned char) | 1 |
sizeof(unsigned short) | 2 |
sizeof(unsigned long) | 4 |
sizeof(unsigned long long) | 8 |
这是在32位情况下的大小,32位各类型指针的大小恒为 4字节
64位各类型指针的大小为8字节
负数求模的规则:
结果的正负号由第一个运算数的正负号决定。
printf("%d\n", 11 % -5); // 1
printf("%d\n", -11 % -5); // -1
printf("%d\n", -11 % 5); // -1
打印的规则
printf("%5d\n", 123); // 输出为 " 123" %5d 表示这个占位符的宽度至少为5位,大于5位则全部输出,少于则在前面补空格
printf("%-5d\n", 123); // 输出为 "123 " %-5d 表示这个占位符的宽度至少为5位,大于5位则全部输出,少于则在后面补空格
printf("%12f\n", 123.45);//输出为 " 123.450000" %12f 表示输出的浮点数最少要占据12位。由于小数的默认显示精度是小数点后6位,所以 123.45 输出结果的头部会添加2个空格。
printf("%6.2f\n", 0.5);//输出为 " 0.50"
printf("%+d\n", 12); // 输出 +12
printf("%+d\n", -12); // 输出 -12
printf("%*.*f\n", 6, 2, 0.5);//输出为" 0.50"最小宽度和小数位数这两个限定值,都可以用*号代替
printf("%.5s\n","hello world");//输出"hello" 最多打印5个
printf("%05d\n",12); //输出 00012,至少5位,不足补0
循环补充
break 的作用是用于永久的终止循环,只要 break 被执行,直接就会跳出这个循环,继续往后执行。continue 的作用是跳过本次循环 continue 后边的代码,在 for 循环和 while 循环中有所差异的。
goto 语句和跳转标号, goto 语句可以实现在同⼀个函数内跳转到设置好的标号处
// goto labell; ;ablell:
随机数的生成
rand函数会返回一个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的
但是大部分编译器上是32767。头文件(stdlib.h) rand函数生成随机数的默认种子是1,即srand(1)
srand,用来初始化随机数的生成器的,用来播种的 srand (unsigned int seed)
通过srand函数的参数seed来设置rand函数生成随机数的时候的种子,只要种子在变化每次生成的随机数序列也就变化起来了
time 函数会返回当前的日历时间,其实返回的是1970年1月1日0时0分0秒到现在程序运行时间之间的差值,单位是秒。time (time_t* timer)返回的类型是time_t类型的,time_t 类型本质上其实就是32位或者64位的长整型类型 long 和 long long
time函数的参数 timer 如果是非NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去,就没有返回值
如果 timer 是NULL或0,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
含头文件:(time.h)
srand((unsigned int)time(NULL))
rand()
变长数组
int b=3;
int a[b];
a[0]=1;a[1]=1;a[2]=2
变长数组不能被初始化,只能被赋值
头文件总览
<assert.h> 条件编译宏,将参数与零比较
<complex.h>(C99) 复数运算
<ctype.h> 用来确定包含于字符数据中的类型的函数
<errno.h> 报告错误条件的宏
<fenv.h>(C99) 浮点环境
<float.h> 浮点类型的极限
<inttypes.h>(C99) 整数类型的格式转换
<iso646.h>(C95) 运算符的替代写法
<limits.h> 整数类型的范围
<locale.h> 本地化工具
<math.h> 常用数学函数
<setjmp.h> 非局部跳转
<signal.h> 信号处理
<stdalign.h>(C11) alignas 与 alignof 便利宏
<stdarg.h> 可变参数
<stdatomic.h>(C11) 原子操作
<stdbool.h>(C99) 布尔类型的宏
<stddef.h> 常用宏定义
<stdint.h>(C99) 定宽整数类型
<stdio.h> 输入 / 输出
<stdlib.h> 基础工具:内存管理、程序工具、字符串转换、随机数、算法
<stdnoreturn.h>(C11) noreturn 便利宏
<string.h> 字符串处理
<tgmath.h>(C99) 泛型数学(包装 math.h 和 complex.h 的宏)
<threads.h>(C11) 线程库
<time.h> 时间 / 日期工具
<uchar.h>(C11) UTF - 16 和 UTF - 32 字符工具
<wchar.h>(C95) 扩展多字节和宽字符工具
<wctype.h>(C95) 用来确定包含于宽字符数据中的类型的函数
整型提升
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升
1. 有符号整数提升是按照变量的数据类型的符号位来提升的
2. 无符号整数提升,高位补0
int main()
{
char - signed char
unsigned char
char a = 5;
5 - int - 4个字节 - 32bit
00000000000000000000000000000101
00000101 - a (截断后存储到a中)
char b = 127;
00000000000000000000000001111111
01111111 - b (截断后存储到b中)
char c = a + b;//发生整型提升
00000000000000000000000000000101 - a
00000000000000000000000001111111 - b
00000000000000000000000010000100 - a+b
10000100 - c
printf("%d\n", c);
这里c还是要整型提升
11111111111111111111111110000100
10000000000000000000000001111011
10000000000000000000000001111100
-124
%d 是按照10进制的形式打印有符号的整数
return 0;
}
算术转换
long double
double
float
unsigned long int
long int
unsigned int
int
由下到上转换
如果某个操作数的类型在上面这个列表中排名靠后,那么首先要转换为另外一个操作数的类型后执行运算。(转换的是补码)
有符号与无符号比较:有符号数会转换成无符号数来进行比较(如:int 与 unsigned int 比较,int 转换成 unsigned int)。(转换的是补码)
逗号表达式
就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
const修饰指针
const 修饰变量,使得这个变量不能被修改 const int n = 100;
const 修饰指针
1. const放在*的左边
限制的是指针指向的内容,意思是不能通过指针来修改指针指向的内容,但是指针变量本身是可以修改的
2. const放在*的右边
限制的是指针变量本身,意思是不能修改指针变量的指向,但是可以修改指针指向的内容
可以同时加:const int * const p = &n;
存储类别
存储类别解决的是标识符的"生命周期"或者变量内存的开辟时间和销毁时间
栈变量:auto(省略不写)声明的变量 (99%)局部变量
int a=10; (auto int a=10;)
变量内存开辟时间:栈变量是在执行到变量定义语句时开辟内存
变量内存销毁时间:所在作用域结束后销毁
静态区变量:用static声明的变量 (1%)局部变量
变量内存开辟时间:编译时
变量内存销毁时间:主函数结束时
作用:1.多次执行时只执行一次且生命周期变长 对于静态化的局部变量来说
2.全局标识符或者函数名如果用static修饰,并不是表示在全局(静态)区而是表示该标识符只能在本文件内被扩展使用,只能在本文件内可见
例 fun.c
#include<stdio.h>
int max=0;
static void fac(void)
{
max=20;
printf("***\n");
}
fac函数加了static之后 只能在fun.c中被使用 不能再被其他文件引用
其他文件想要调用,必须先要包含此文件获得相关函数定义
作用域
作用域:一个代码空间
函数作用域:函数的参数和函数体属于函数作用域,函数的返回值和函数名属于文件作用域
文件作用域:从文件头到文件尾的代码空间
#include<stdio.h>
int c=10;文件作用域
void fun(int b);文件作用域
int main()
{
int a=10; 函数作用域
a=20;
}
void fun(int b)
{
b=30; 函数作用域
}
结构体也有作用域
语句块作用域
int main()
{
int a=10;
a=20;
{
int j=0;语句块作用域
j=50;
}
a=fun(5);
}
一个标志符作用域可以包含,但不能存在相交与重合
补充:作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
1. 局部变量的作用域是变量所在的局部范围。
2. 全局变量的作用域是整个工程。
生命周期指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段。
1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
2. 全局变量的生命周期是:整个程序的生命周期。
全局变量与局部变量
全局变量和函数名属于文件作用域内的标识符。
局部变量和函数体属于函数作用域内的标识符。
文件作用域内或者函数作用域内的标识符是可以通过extern扩展作用域的
extern的拓展作用
例1
#include<stdio.h>
extern int c;
main()
{
int c;
c=20;
printf("%d",c);
}
例2
extern 需要在同一工程下调用不同文件