C语言常识
-
# 标识符,告诉编译器 # 后边的进行替换
-
include,包含头文件的路径
-
< > 表示头文件直接去 C 库查找, "" 表示先在当前路径下找头文件,如果没有再去 C 库找
-
stdio.h 是标准输入输出的头文件,C语言中头文件不一定必须是 .h 后缀,但是书写传统 都是以 .h 为后缀作为头文件
此文件中声明了标准 C 库的标准输入输出函数 如 :printf scanf gets puts 这些函数的逻辑被编译成标准 C 库的二进制文件
-
int 是main函数的返回值,类型也可以是 void 类型
-
main 主函数名字也标记了 C 程序的入口,程序从这个地方开始执行
-
(形参列表) ()内也可以不写形参 建议不传参时加上 void 标识一下
{
return 0;
}
-
{}作用域标记符
-
花括号中 return 表示返回也是 C 语言中的一种跳转语句,也是出栈的一个标识
-
; 表示告诉编译器 ; 标识的这句话参与编译
-
C语言中,有且仅有一个 main 函数
-
C语言本质就是操作内存
-
在编写 C 语言程序是一定要区分中文字符与英文字符,所有的标记符都是英文的
-
关于头文件:
C语言中 一般头文件 以 .h 作为后缀
.h 文件中一般都是函数及变量的声明 没有变量赋值操作
-
①//注释
②/* 注释 */
一、内存概念
位称为 bit ,一个二进制位只能表示要么0要么1
字节为byte 一个字节 由 8个bit位表示(构成)
KB = 1024个 字节
MB = 1024个 KB
GB = 1024个 MB
TB = 1024个 GB
计算机内存是以每一个字节进行编号 从 0 开始,用十六进制数表示 ,这个编号简称 内存地址
二、计算机内存申请方法
1. 定义变量
存储类型 + 数据类型 + 变量
例:auot int a
存储类型: 主要是在哪里申请空间
auto :系统自动分配,如果不标记默认是由系统分配
static :静态区,空间利用周期随程序结束而结束,标定文件使用
const :只读区,只可以读取空间内的数据 不可以修改
extern :外部的(主要针对文件来说)
register :寄存器,在 CPU 内部申请空间
(因为 CPU 内部寄存器个数有限,所以不一定能够申请到 如果申请不到的话,则默认转为 auto ,CPU 内部寄存器与 CPU 数据交互速度快,且 register 申请的空间不可以进行取地址操作,没有地址编号,所以一般开发不常用)
数据类型: 主要表示申请多大的空间以字节为单位
基本类型
-
字符型:表示日常用的符号 char 占1个字节,能够表示十进制 256 个数据
-
短整型:表示日常的整数表示 short 占 2个字节,能够表示十进制 65536 个数据
-
整型:表示工程开发中一般用 int 表示整形数据 int 占 4个字节,能够表示十进制 42 亿多个数据
-
长整型:
long int :32位操作系统占 4个字节,64位操作系统占 8个字节
-
实型(浮点)
单精度: float 占 4个字节
双精度: double 占 8个字节
多精度: long double 占 32 位系统 12 字节 ,64位系统 16 字节
枚举类型:
enum
构造类型:
数组 char c[10]
结构体 struct
共用体 union
指针类型:
数据类型 *
char *
int *
void *
空类型:
void
变量名: 相当于是给申请到的空间取一个名字
2.手动申请 malloc分配 空间开辟在堆区
三、输入输出
1. printf("%d",a)
2. scanf("%d",&a)
3. 占位符:
%d : 打印十进制整型数据
%o : 打印八进制
%x : 打印十六进制
%c : 打印字符
%s : 打印字符串
%u : 打印无符号十进制整型
%ld :打印长整型
%f : 打印单精度浮点型,默认打印小数点后6位。%.nf ,n 是保留小数点后的位数
%Lf: 打印双精度浮点型
%p: 打印申请到的空间地址数据
%e: 指数数形式打印
%#x :打印十六进制数会有 0x
%#o :打印八进制数会有 0
有一些占位符scanf不能使用,printf通用
四、运算符
注:优先级从上到下排列
单目运算符:
+ 正数
- 负
+ + 自增
- - 自减
* 指针相关
& 指针相关
!真假取反
~ 按位取法
算数运算符:
+ 加
- 减
* 乘
/ 除
% 取余(也叫取模)(浮点数不能进行取余运算)
位移运算:
<< 左移
>> 右移
关系运算:
> 大于
< 小于
== 等于
!= 不等于
>= 大于等于
<= 小于等于
位运算:
& 按位与
^ 位异或
| 位或
逻辑运算:
&& 逻辑与
|| 逻辑或
条件运算符:
?:
a = a>b?a:b 如果?前的表达式为真,就执行 : 左侧的表达式;否则执行 :右侧表达式
赋值运算符:
==
+=
-=
*=
/=
&=
|=
>>=
<<=
逗号运算符:
,
运算符优先级次序可以用()来限制优先级次序
五、控制语句
控制语句是实现程序逻辑的 ,控制着代码的执行与否及执行多少次
1. 条件判断 if 语句
-
单分支 if(表达式) //如果表达式为真,则执行语句;为假则不执行 //C 语言中真假判断 0 为假,非 0 为真 { 执行语句; }
-
双分支 if(表达式) { 执行语句1; } else { 执行语句2; }
-
多分支 if(表达式 1) { 执行语句1; } else if(表达式 2) { 执行语句 2; } else { 执行语句 3; }
2. 开关switch语句
-
switch(表达式) //此处表达式一般是整型变量 { case 表达式 1:执行语句 1; //case 后边的表达式 一般是常量表达式 break; case 表达式 2:执行语句 2; break; case 表达式 3:执行语句 3; break; case 表达式 n:执行语句 n; break; case 表达式 n+1:执行语句 n+1; break; default: 执行语句; }
3.循环语句 for / while / do while
-
for(<表达式1>;<表达式2>;<表达式3>) { 循环语句; }
-
while(<表达式>)//若干表达式一般为关系运算为真,则执行循环语句 为假 则不执行 { 循环语句; }
-
do { 代码块; } while(表达式1);
4. 跳转语句
continue : 结束此次循环,执行下一次循环 continue 后的语句不再执行
break :跳出整个循环
goto :一般少用 goto 容易出现 bug 能避免则避免
return :结束程序,跳出整个程序
六、数组
数组是相同数据类型的有序集合
数组的表现形式:
存储类型 + 数据类型 + 数组名 + [常量表达式]
例:auto char a [50]
数组赋值:
-
数组数据访问 从 0 开始 a[0] a[1] a[2] ... a[49] 共50个
其中 [] 内的数字 表示数组的 下标,所以说 数组下标是从 0 开始的
数组赋值也是根据下标进行复制的
比如
a[0] = 98;
a[1] = 78;
a[2] = 55;
a[40] = 88;
数据内存分配:
- 数组分配的内存是连续的
数组初始化:
-
未初始化的数组
int a[5];
-
完全初始化
int a[5] = {1,2,3,4,5};//一定要加分号
-
不完全初始化
int a[5] = {1,2,3};
-
完全初始化为 0
int a[5] = {0};
数组访问不可以越界:
比如 int a[5] = {1,2,3,4,5};
a[5] = 500;//如此操作可以么???
不可以 ,虽然编译通过且可以运行,但因为访问越界 会改变或读取错误数据.
[]:在C语言数组中叫做下标运算符,定义a[n],[]不可超过n,也不可小于0
数组名是数组的首地址,它是一个地址“常量”
七、指针
指针是地址数据
指针变量就是开辟一段空间,空间内只能存储 地址数据
指针变量定义:
存储类型 + 数据类型 * + 变量名
例:auto int * a,数据类型可以是任意类型
//定义一个整型指针变量
auto int *p; //在 32 位操作系统下,任何数据类型的指针变量都占 4 字节, 64 位操作系统占 8 字节
//定义一个字符类型的指针变量
char *s; // 32 位操作系统 也占 4 字节
指针变量赋值:
p = &a;//& 在指针环节表示变量取地址的意思,这一句就是将 a 空间的首地址数据 ,存入 p 空间内 也叫作 p 指向 a
指针的定义:
-
指针使用前 一定要初始化 未初始化的指针称为 野指针,直接使用野指针是
非常非常非常危险的事情!!!
-
int *p;
int a;
*p = 300;
//不允许如此操作,p 是未初始化的指针变量,内部存储的数据不确定
//如果直接操作随机地址是很危险的。所以操作系统内存保护机制会直接停止程序
//未初始化的指针 叫做野指针 是不可以直接使用的
指针与数组:
数组名是数组的首地址, 如何用指针指向数组呢???
int a[5] = {1,2,3,4,5};
int *p;
p = a;
//p++,相当于指针变量 p 自增 ,指针变量,每一次自增所增加的字节宽度 是它自身数据类型所占的字节宽度
//又因为数组的内存是连续分配的,所以连续打印&p即可连续展现出整个数组
常量指针和指针常量:
"常量"指针:
指针的指向可以改变 但指针指向的空间内的数据不可被改变
const int *p;
指针“常量”
指针指向不可被改变 但指针指向的空间内的数据可以被改变
int *const p;
二级指针
int a = 100;//普通变量存储 普通数据
int *p = &a;//一级指针 存储普通变量地址
int **q = &p;//二级指针 存储一级指针变量地址
八、函数
数组是对 相同数据类型的封装
函数是对 代码的封装
函数是实现特定功能的一段代码
函数三要素:
- 功能(函数是用来干什么的)尽量做到见名知意
- 参数(形参列表的参数个数、数据类型、顺序、及意义)建议设计参数个数不要超过 4 个
- 返回值(函数执行结束后返回的数据 数据类型及意义) ,可以没有(void)
函数的声明:
返回值类型 + 函数名 + (形参列表)
int add (int a, int b);
返回值为 整型 ,函数名 add , 参数两个 ,数据类型 int a 、b
功能: 计算两个数的和
参数: a 要参与运算的变量 int 类型,b 要参与运算的标量 int 类型
返回值:返回a 和 b 相加的int型结果
函数内存:
函数只有在被调用时才会分配内存,用完即释放掉内存
九、结构体
结构体是用户自定义数据类型
数组是对相同数据类型的封装,那么结构体就是对不相同数据类型的封装
- 结构体是数据类型,本身不占内存,只有在成员被定义的时候才会分配内存
struct Student
{
int number,age;//int型学号和年龄
char name[20],sex;//char类型姓名和性别
float score;
};//此时并没有分配内存
struct Book
{
char title[20];//一个字符串表
char author[20];//一个字符串表示的author作者
float value;//价格表示
};//这里只是声明 结构体的定义
struct Book book1,book2;//结构体变量的定义 分配空间
book1.value;//引用结构体变量
定义结构体变量以后,系统就会为其分配内存单元
- 结构体变量的初始化时不能跳过赋值,只能按照顺序一个一个赋值,如果前面的赋值了,后面的没有。则默认为NULL(‘0’)
struct Student
{
char name[20];
char sex;
int number;
};
struct Student stu1={"Q大帅",'M',12345};
- 使用结构体变量
a = stu1.name;
b = stu1.sex;
c = stu1.number;
尽可能囊括C语言概要,当然本人能力有限,欢迎大家评论补充!