c语言知识点总结

c语言

数据类型和基础

输出格式

  • %5d :五个终端位宽,右对齐
  • %-5d :5个终端位宽,左对齐
  • %05d :5个终端位宽,右对齐不足补零

进制之间

  • 八进制 编写时前面加0: 010==0

  • 十六进制 ox: 0x12 == 18

  • 二进制 01

  • 十进制

  • 不同数据的计算机存储和读取

    • 存储

      • 负数:补码
      • 其他:原码
    • 读取

      • 有符号取:%d.%hd.%ld

        • 最高位为0:原样输出
        • 最高位为1:符号位不变取反+1
      • 无符号取:%u,%x,%o,%lu

register

  • 定义寄存器变量

volatile

  • 作用:防止编译器优化,强制访问内存操作

typedef 给已有的类型取个别名

数据类型

  • 基本数据类型

    • char 1B
    • short 2B
    • int 4B
    • long 4B(32位系统)
    • double 8B
    • float 4B
  • 无符号和有符号

    • unsigned

      • 特点:没有符号位
    • signed

      •   特点:有符号位,1为负,0为正
        
  • 测量类型长度

    • sizeof()
  • 数据类型的转换

    • 自动类型转换

      • signed int >> unsigned int >> long >>double
      • char,short参加运算就用int型
    • 强制类型转换

      • 当前有效,后面不会更改

运算符

优先级

算术运算符

  • /

    • 整数相除,结果取整
    • 只要有一个浮点数,除法运算
  • %

    • 取余

      • 必须为整数

逻辑运算符

  • !逻辑非

    • !0==真
    • !真==0
  • &&逻辑与

    • 同真则真
    • 短路特性:前假不管后
  • || 逻辑或

    • 同假则假
    • 短路特性:前真不看后

二进制运算符

  • & 按位与

    • 全1为1,其他为0
    • 特点:和1相与,保持不变,和0相与,清零
    • 将固定位清零
  • | 按位或

    • 全0为0,其他为1
    • 特点:和0相或,保持不变,和1相或,置1
    • 将固定位置1
  • ~ 按位取反

    • 0变1,1变0
  • ^ 按位异或

    • 相同为0,不同为1
    • 特点:和0异或,不变;和1异或,取反
    • 将固定位发生高低电频的翻转
  • << 左移运算符

    • 左边丢弃,右边补零
  • 右移运算符

    • 逻辑右移

      • 右边丢弃,左边补零
    • 算数右移

      • 有符号数

        • 正数
        • 负数:左边补1
      • 无符号数

其他运算符

  • ? : 表达式?值1:值2

  • 逗号运算符

    • 表达式的值为最后一个表达式的值
  • 符合运算符

    • +=,-=,*=,%=
  • ++ ,–运算符

判断语句

if

  • if ()……
  • if() …… else
  • if() ……else if()……else if()……

switch

  • break

循环语句

for(初始语句;循环条件;步进条件)

  • break:跳出最近的一个循环
  • continue:跳出本次循环

while(循环条件)

  • 没有初始语句,没有步进语句

do……while(循环条件)

  • 先执行后判断

goto

  • 跳转到goto指向的地方

数组

概述:具有相同类型的变量,用连续的空间存储起来,这样的数据结构就是数组

数值数组

  • 一维数值数组

    • 定义时候[]里的值不能是变量

    • 初始化:

      • 全部初始化

        • int arr[3]={1,2,3};
      • 部分初始化

        • int arr[3]={0};
    • 输入和输出需要循环 arr[i]

  • 二维数值数组

    • 初始化

      • 分段初始化:{}里的{}明确每一行
      • 连续初始化:放满一行才能放下一行

字符数组

  • 一维字符数组

    • 初始化

      • 逐个字符
      • 字符串形式
    • 遍历

      • 循环逐个遍历
      • 整体遍历%s
    • 获取键盘字符串

      • scanf:遇到空格结束输入

      • gets:容易造成内存污染

      • fgets:解决两者问题,但是会有\n输入

        • strtok
        • strlen-1
  • 二维字符数组

    • 存放多个字符串,每个字符串占一行

    • 输出

      • 输出一个字符串,仅仅只需要用行标即可
      • 输出某个字符时,用到行标和列标
    • 键盘获取输入

      • 字符串个数决定行数
      • 字符串中最大长度决定列数
    • 地址

      • 二维数组名代表的是首行地址,+1跳过一行
      • 对行地址取*,将变成当前行的第0列的列地址

函数

定义

  • 返回值、函数名、形参、函数体

声明

  • 返回值、函数名、形参
  • 告诉编译器函数存在,请通过编译

调用

  • 函数名+实参

函数参数

  • 形参不写,实参可传,但得不到使用

  • 实参

  • 形参

    • 本质:局部变量
    • 函数定义时不会开辟空间,只有调用时才开辟空间
    • 在函数结束的时候 才被释放

函数名

  • 代表函数入口地址

返回值

  • <=4B,存放寄存器
  • 4B,存放栈区

全局函数和静态函数

  • 全局函数

    • 其他源文件可使用,需加extern
  • 静态函数

    • static +函数

    • 只能在当前源文件使用

    • 可封装在全局函数里,被其他源文件使用

      • 与全局函数位于同一个源文件

形参。返回值都存在栈区

变量

存放:
生命周期:
不初始化:
生效位置:

普通变量

  • 普通局部变量

    • 最近的{}生效
    • 存放 栈区
    • 生命周期:离开{}就回收
    • 不初始化,内容不确定
    • 同名就近原则
  • 普通全局变量

    • 定义在函数外边的变量,当前源文件都有效
    • 存放 全局区
    • extern:其他源文件也可使用
    • 生命周期:进程结束释放
    • 不初始化,内容为0

静态变量(static修饰)

  • 静态局部变量

    • {}生效
    • 存放 全局区
    • 生命周期:整个进程
    • 不初始化,内容为0
    • 只能被定义一次
  • 静态全局变量

    • 定义在函数外边,当前源文件生效
    • 存放 全局区
    • 生命周期:整个进程
    • 不初始化,内容为0

宏(后面不加分号!!)

  • define

    • 不带参数的宏:#define N 10

    • 带参数的宏: #define N(a,b)a+b

      • 做不到完整性

      • 带参数的宏函数和普通函数的区别

        宏函数:调用多少次,就展开多少次,执行代码的时候,没有函数调用的过程也不需要函数的出入栈,浪费了空间,节省了时间
        普通函数:代码只有一份,存放在了代码段,调用时候出入栈,所以函数节省了空间,浪费了时间

      • 子主题 3

  • undef

    • 终止宏的作用

头文件包含

<> :从系统指定目录下寻找

“” : 从源文件所在目录下找,没找到就去系统指定目录下找

防止头文件重复包含

  • 1、 #pragma once
  • 2、 #infdef
    #define
    #endif

原码,反码,补码

只有负数在计算机中存储的是补码

补码的意义

  • 1、将减法运算变加法运算
  • 2、统一0的编码

指针

指针变量

  • 本质是一个变量,存放内存的地址编号

  • 32位平台,任何类型地址编号都是4字节

  • 定义:*

    • 前提:明确保存啥类型变量的地址
  • 使用 *p

    • 表示取p所保存的地址编号对应的空间内容(指针变量p的解引用)
  • 类型

    • 自身类型

    • 指向类型

      • 宽度
      • 跨度
  • 初始化

    • NULL
    • 局部指针变量不初始化保存随机地址编号
    • 初始化为合法空间
  • 使用时

    • 取地址&
    • 取 *
  • 注意事项

    • void不能定义变量,void * 可以定义变量

      • void *p

        • 不能直接对*p操作
        • p强制类型转换后,再*操作
    • 没有初始化的指针变量不能取*

    • 初始化为NULL的指针变量不能取*(更改后可以)

    • 不要给指针变量赋普通的数值

    • 不要操作越界空间

数组单个元素的指针

  • 指针变量保存数组首元素的地址

  • p+i :第i个元素的地址

  • []和*()的关系

    • []是*()的缩写
    • *(p+i)==p[i]
    • 加法的交换律:p[i]==i[p]
  • arr和&arr的区别

    • arr首元素的地址,+1跳过一个元素
    • &arr首地址,+1跳过整个数组
  • 数组名是个符号常量不能被赋值

  • 指向同一数组的两个元素的指针

    • 相减=相差个数

    • 比较大小

      • p1、p2比较的是存放的元素的地址
    • 指针之间可以赋值

    • 不可相加

指针数组

  • 本质是数组(栈区),数组的每个元素是指针
  • int *arr[10]

数组指针

  • 本质是一个指针,保存数组首地址

  • 要注意

    • char (*p3)[5] = &a;√
    • char (*p4)[5] = a;×

多级指针

  • **p

指针变量作为函数的参数

  • 外部变量地址传给函数内部,从而修改外部变量的值
  • 一维数组作为函数形参,会被优化成一级指针变量
  • 二维数组作为函数形参,会被优化成数组指针 int arr[3][4]-------->int (*p)[4]
  • 指针作为函数的返回值,函数不要返回普通局部变量的地址
  • 函数名代表的是函数的入口地址

动态内存分配(堆区)

malloc

void *malloc (unsigned int num_size);

  • 清空

    memset(str ,0,size);

calloc

void *calloc(size_t nmemb , size_t size);
nmemb:申请的块数
size:每一块的大小

realloc

void *realloc(void *s,unsigned int newsize);

在原先s指向的内存基础上重新申请内存,新的内存的大小为 new_size 个 字节,如果原先内存后面有足够大的空间,就追加,如果后边的内存不	够用,则realloc函数会在堆区找一个newsize个字节大小的内存申请,将原先内存中的内容拷贝过来,然后释放原先的内存,最后返回新内存的地址

free

free();

  • 防止多次释放

    if(p != NULL)
    {
    free§;
    p=NULL;
    }

字符串处理函数

str

  • strlen

    size_t strlen(const char *s)
    返回值为 字符串的长度 不包含’\0’

  • strcpy

    char *strcpy( char *dest, const char *src )

    • strncpy

      char *strncpy( char *dest, const char *src,int num)

    • 若拷贝的位置已经存在字符串,则清空然后拷贝(系统自动清空)

  • strcat

    char *strcat(char *dest, const char *src);

    • strncat
  • strcmp

    int strcmp(const char *s1, const char *s2);

    • strncmp
  • strchr

    char *strchr(const char *s, int c);
    从字符串s中查找第一次c字符出现的地址

  • strstr

    char *strstr(const char *s1, const char *s2);
    从s1中查找字符串s2 返回第一次s2出现的地址

将字符串转为数值

  • atoi
  • atol
  • atof

strtok

char *strtok(char *str, const char *delim);

  • 切割代码

    while(1) { arr[i] = strtok(arr[i],"😊; if(arr[i] == NULL) break; i++; }

    while(arr[i++] = strtok(arr[i],"😊);

子主题 4

sprintf、sscanf

sprintf组包

sscanf解包

  • 流指针提取,提取时遇到非要求的就停止

  • 使用%*s %*d 跳过提取的内容(不要提取的内容)

  • 使用%[n]s %[n]d 提取指定宽度n的字符串或数据

  • %[a-z] 提取a-z的字符串

  • %[aBc] 提取 a B c

  • 子主题 6

    • %[^abc] 只要不是a b c任何一个 都要

const

修饰变量为只读

const int *p;

  • const在的左边 表示 const 修饰的是 而不是 p.
  • 效果:用户不能借助*p更改空间的内容 但是 p可以指向其他空间(*p 只读 p可读可写)

int * const p;

  • const 在的右边 const修饰的是p 而不是
  • 用户可以通过*p 修改p所指向空间的内容 但是 不能再更改p的指向(*p可读可写 p只读)

结构体

初始化

  • 类型与结构体内类型一致

清空结构体

  • memset(&stu,0,sizeof(stu));

获取

  • 逐个获取

    scanf("%d %s %d",&lucy.num, lucy.name , &lucy.age);

结构体之间的赋值

  • 方式一:逐个成员赋值

    • bob.num = lucy.num;
  • 方法二:相同类型的结构体变量 可以直接赋值(推荐)

    • bob = lucy;
  • 方法三:方法二的底层实现

    • memcpy(&bob,&lucy,sizeof(struct stu));

结构体数组

结构体指针

结构体的内存对齐

  • 确定方法

    • 1、确定分配单位:每一行该分配的字节数
    • 2、确定成员的起始位置的偏移量==成员的基本类型整数倍
    • 3、收尾工作:结构体总大小==分配单位的整数倍
  • 结构体嵌套结构体(一定要访问到最底层)

    • 1、确定分配单位:每一行该分配的字节数由所有结构体中最大的基本类型决定
    • 2、确定成员的起始位置的偏移量成员的基本类型整数倍
      结构体成员的偏移量
      结构体中最大基本类型的整数倍
      结构体成员的成员的偏移量==成员的基本类型的整数倍
    • 3、收尾工作:结构体总大小分配单位的整数倍
      结构体成员的总大小
      倍嵌套的结构体里面最大基本类型的整数倍
  • 强制类型对齐

    • #pragma pack (value)

位段(位域)

  • 相邻位段可以压缩,但不能超过成员自身大小(多个)
  • 位段的赋值不要超过位段的大小,会产生数据的错乱
  • 从低位到高位存放

与共用体(union)的区别

  • 共用体:

    • 所有成员共享一份空间
    • 空间大小由最大成员决定
    • 注意:数据存放倒着存时候

链表

  • 物理存储上非连续,数据元素的逻辑顺序通过链表指针连接次序

  • 动态生成每个节点

  • 节点包括数据域和指针域

  • 链表的插入

    • 为插入的节点申请空间

      • 判断节点存在

        • 不存在,直接赋给头节点

        • 存在

          • 头部之前插入

            • 指针域指向头部,头部指向新的头
          • 尾部插入

            • 寻找尾节点,尾节点的指针域连接上插入的节点
          • 有序插入

            • 1、确定插入位置
            • 2、判断插入位置
  • 链表的查询

    • 1、判断存在节点
    • 2、逐个节点查询
  • 链表的删除

    • 1、判断存在节点

    • 2、节点存在

      • 找到删除点

        • 头节点
        • 中节点
        • 尾节点
  • 链表的释放

    • 逐个释放

      • 头指向下一个节点的位置,再释放此节点
  • 链表的遍历

  • 链表的逆序

    • 循环前提:pb保存head->next,将head->next置NULL
    • 1、pr保存pb->next,原因:pb->next会指向head
    • 2、pb->next 指向 head,原因:逆转方向
    • 3、保存 逆转方向的代码 可以重复 执行
  • 双向链表

    • 双向循环链表

深拷贝和浅拷贝

  • 指针作为结构体的成员

    • 操作前,必须有合法的空间(ralloc)

      • 指向堆区空间的话,一定要释放
  • 浅拷贝

    • 只申请一次堆区空间,释放两次出问题
  • 深拷贝

    • 为每个结构体指针变量申请独立的堆区空间,释放不会出错

文件

缓冲区:提高存取效率,延长磁盘使用寿命

磁盘文件分类

  • 物理:都是二进制存储,顺序存储

  • 逻辑:

    • 文本文件:字符编码

      • 译码容易
      • 占用空间大
    • 二进制文件:值编码

      • 空间利用率高
      • 特殊的解码器

文件指针:FILE *fp

fp=fopen(文件名,文件使用方式);

  • r

    • rb

      • 不创建
  • w

    • 不存在,创建;存在,清空,再操作;
  • a

    • 不存在,创建;存在,文件结尾处操作
    • 可读可写

      • r+

        • 不创建
      • w+

        • 创建
      • a+

        • 创建,添加
  • b

    • 二进制方式打开
  • t

    • 文本打开(省略)

fclose(文件指针)

  • 关闭成功,返回0

文件读写

  • 字节读写

    • fgetc(fp);
    • fputc(ch,fp);
  • 字符串读写

    • fgets(str,n,fp);

      • n:字符数,要获取n-1个字符
    • fputs(字符串,fp);

  • 块读写

    • fread(buffer,size,count,fp);
    • fwrite(buffer,size,count,fp);
  • 格式化操作

    • fprintf(文件指针,格式字符串,输出表列);

      fprintf(fp,“英雄:%s 防御:%d 攻击:%d\n”,hero[i].name, hero[i].deff,hero[i].atk);

    • fscanf(文件指针,格式字符串,输出表列);

  • 复位文件流指针

    • rewind(文件指针);
  • 获取文件长度

    • long=ftell(文件指针);
  • 文件流指针定位

    • fseek(文件指针,位移量,起始点);
  • feof():判断文件是否到达文件末尾

排序方式

冒泡排序

//排序
for(i=0;iarr[j+1])
{
int flag = 0;
for(j=0;j<n-1-i;j++)
{
int tmp = 0;
tmp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
flag = 1;
}

if(flag == 0)//数组已经有序 
break;

}

  • 相邻比较,大下沉,小上升
  • 在外层循环和内层循环之间加一个初始化的变量,在内层循环给它赋值,可以判断出是否进行了内层循环,从而达到减少循环次数的目的
  • 最先确定位置的是最后一位,逐渐向前确定

选择排序

  • 每次外循环只进行一次交换
  • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值