ps:先举三反一,再举一反三,学习就应该是这样,先模仿,再改进,最后实现自己的创意! –小甲鱼论坛
C语言中各种数据类型所占用的存储空间的大小
int—32位 四个字节
float —32位 四个字节
char—8位 一个字节
double—-64位 8个字节
bool—-16位 2个字节
long—-32位 四个字节
整数类型
下表列出了关于标准整数类型的存储大小和值范围的细节:
类型 | 存储大小 | 值范围 |
---|---|---|
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 字节 | 1.2E-38 到 3.4E+38 | 6 位小数 |
double | 8 字节 | 2.3E-308 到 1.7E+308 | 15 位小数 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 | 19 位小数 |
void 类型
void 类型指定没有可用的值。它通常用于以下三种情况下:
序号 | 类型与描述 |
---|---|
1 | 函数返回为空 C 中有各种函数都不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status); |
2 | 函数参数为空 C 中有各种函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void); |
3 | 指针指向 void 类型为 void * 的指针代表对象的地址,而不是类型。例如,内存分配函数 void *malloc( size_t size ); 返回指向 void 的指针,可以转换为任何数据类型。 |
C语言运算符优先级
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
---|---|---|---|---|---|
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | |
() | 圆括号 | (表达式)/函数名(形参表) | |||
. | 成员选择(对象) | 对象.成员名 | |||
-> | 成员选择(指针) | 对象指针->成员名 | |||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
(类型) | 强制类型转换 | (数据类型)表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | 单目运算符 | ||
– | 自减运算符 | –变量名/变量名– | 单目运算符 | ||
* | 取值运算符 | *指针变量 | 单目运算符 | ||
& | 取地址运算符 | &变量名 | 单目运算符 | ||
! | 逻辑非运算符 | !表达式 | 单目运算符 | ||
~ | 按位取反运算符 | ~表达式 | 单目运算符 | ||
sizeof | 长度运算符 | sizeof(表达式) | |||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | 双目运算符 | ||
% | 余数(取模) | 整型表达式/整型表达式 | 双目运算符 | ||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | 双目运算符 | ||
5 | « | 左移 | 变量«表达式 | 左到右 | 双目运算符 |
» | 右移 | 变量»表达式 | 双目运算符 | ||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | 双目运算符 | ||
< | 小于 | 表达式<表达式 | 双目运算符 | ||
<= | 小于等于 | 表达式<=表达式 | 双目运算符 | ||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | 双目运算符 | ||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | |
/= | 除后赋值 | 变量/=表达式 | |||
*= | 乘后赋值 | 变量*=表达式 | |||
%= | 取模后赋值 | 变量%=表达式 | |||
+= | 加后赋值 | 变量+=表达式 | |||
-= | 减后赋值 | 变量-=表达式 | |||
«= | 左移后赋值 | 变量«=表达式 | |||
»= | 右移后赋值 | 变量»=表达式 | |||
&= | 按位与后赋值 | 变量&=表达式 | |||
^= | 按位异或后赋值 | 变量^=表达式 | |||
|= | 按位或后赋值 | 变量|=表达式 | |||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | 从左向右顺序运算 |
注:同一优先级的运算符,运算次序由结合方向所决定。
break和continue语句区别
break语句
结束当前循环
continue语句
- 跳过本次循环
二维下标直接索引和指针间接索引的相互转化
|
|
二维数组和数组指针的关系
|
|
void指针和NULL指针
Void指针
- void指针我们把它称之为通用指针,就是可以指向任意类型的数据。也就是说,任何类型的指针都可以赋值给void指针。
|
|
NULL指针
当你还不清楚要将指针初始值为什么地址时,请先将它初始化为**
NULL
**;在对指针进行解引用时,先检查该指针是否为NULL。这种策略可以为今后编写大型程序 节省大量的 调试时间。1
#define NULL ((void *)0)
|
|
指向指针的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
int main(){ int num = 520; int *p = # int **pp = &p; printf("num: %d\n", num); printf("*p: %d\n", *p); printf("**PP: %d\n", **pp); printf("&p: %p, pp:%p\n", &p, pp); printf("&num:%p, p:%p, *pp:%p\n", &num,p,*pp); return 0; } out: num: 520 *p: 520 **PP: 520 &p: 0061FF14, pp:0061FF14 &num:0061FF18, p:0061FF18, *pp:0061FF18
指针数组和指向指针的指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
int pointer_array(){ char *cBooks[] = { "<c程序设计语言>", "<c专家编程>", "<c和指针>", "<c prime plus>", "<C study>" }; char **byLuenci; char **byGood[4]; byLuenci = &cBooks[4]; byGood[0] = &cBooks[0]; byGood[1] = &cBooks[1]; byGood[2] = &cBooks[2]; byGood[3] = &cBooks[3]; printf("Luenci拥有的书: %s\n", *byLuenci); printf("Luenci喜欢的图书有:\n"); int i; for (int i = 0; i < 4; ++i) { printf("%s\n",*byGood[i]); } return 0; } out: Luenci拥有的书: <C study> Luenci喜欢的图书有: <c程序设计语言> <c专家编程> <c和指针> <c prime plus>
常量
- 定义
|
|
指向常量的指针
- 指针可以修改为指向不同的常量
- 指针可以修改为指向不同的变量
- 可以通过解引用来读取指针指向的数据
- 不可以通过解引用修改指针指向的数据
|
|
函数
结构
|
|
函数的声明
所谓的声明(Declaration),就是告诉编译器我要是用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我将会把它补上。
函数的参数和返回值
|
|
形参和实参
- 用于数据传输,形参就相当与一个占位符,只在函数内部有效。
传值和传址
|
|
传数组
- 实际上传过去的是数组的地址
|
|
可变参数
- 引入 头文件**#include<stdarg.h>**
|
|
指针函数
- 使用指针变量作为函数的返回值,就是指针函数
|
|
- PS:不要返回局部变量的指针
函数指针
- 指针函数 - - > *int p();
- 函数指针 - - > *int (p)();
函数指针作为参数
|
|
函数指针作为返回值
|
|
局部变量和全局变量
局部变量
- 不同函数的变量无法相互访问
全局变量
- 如果不对全局变量进行初始化,那么它会自动初始化为0.
- 如果函数在内部存在一个与全局变量同名的局部变量,编译器不会报错,而是在函数中屏蔽全局变量。
exsten关键字
- 告诉编译器我等下会定义变量,不要报错
不要大量的使用全局变量
- 使用全局变量会使你的程序占用更多的内存,因为全局变量从定义时候开始,知道程序退出才释放。
- 污染命名空间
- 提高了程序耦合性
作用域和链接属性
- 当变量被定义在不同的位置时,它的作用域的范围是不一样的,这个作用范围就是我们所说的作用域
- C语言编译器可以确认四种不同类型的作用域:
- 代码块的作用域
- 文件作用域
- 原型作用域
- 函数作用域
代码块作用域(Block scope)
- 在代码块中定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志代码块结束的大括号(})处。
文件作用域(file scope)
- 任何在代码块之外声明的标识符都具有文件作用域,作用域的范围是从他们的声明位置开始,到文件的结尾处都是可以访问的。
原型作用域(prototype scope)
- 原型作用域只适用于那些在函数原型中声明的参数名。
函数作用域(function scope)
- 函数作用域只适合于goto语句的标签,作用将goto语句得标签限制在同一个函数内部,以防止出现重名的标签。
定义和声明
- 当一个变量被定义的时候,编译器为变量申请内存空间并填充值
- 当一个变量被声明的时候,编译器就知道该变量被定义在其他地方
- 声明是通知编译器该变量名及相关的类型已经存在,不需要再为此申请内存空间。
- 局部变量即是定义又是声明
- 定义只能来一次,否则就叫做重复定义某个同名的变量;而声明可以由你很多次。
链接属性
external(外部的)
多个文件中声明的同名标识符表示一个实体
internal(内部的)
- 单个文件中声明的同名标识符表示同一个实体
none(无)
- 声明的同名标识符被当做独立的不同实体
只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用域的标识符都是none属性。
默认情况下,具备文件的作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是一个实体。
使用static关键字可以使得原先拥有的external属性的标识符变为internal属性。这里有两点需要注意:
- 使用static关键字修改链接属性,只对具有文件作用域的标识符生效(对于拥有其他作用域的标志符是另一种功能)
- 链接属性只能修改一次,也就是说一旦将标识符的链接属性改为internal,就无法变回external。
生存期和存储类型
C语言变量拥有两种生存周期
静态存储器
自动存储器
具有文件作用域的变量属于静态存储器,函数也属于静态存储器。属于静态存储器的变量在程序执行期间将一直占据存储空间,直到程序关闭才释放
具有代码块作用域的变量一般情况下属于自动存储器。属于自动存储期的变量在代码块结束时将自动释放。
存储类型
- 存储类型其实是指存储变量值的内存类型,C语言提供了五种类型。
- auto
- register
- static
- extern
- typedef