当前位置: 首页 > news >正文

C语言基础补全

基础巩固

一. 程序

1. 程序为什么要经过编译器编译才能运行

  • 计算机能识别的只有机器语言

    • 机器语言: 二进制代码. 由 01 组成 010101 等指令
  • 机器语言难记, 为方便编写程序增加易记忆的助记符, 汇编语言便应运而生

  • 在汇编语言基础上为了更进一步方便编写程序, 高级语言登场了

    • 高级语言: C、C++、Java、python 等
  • 高级语言编写的程序虽好, 但计算机无法识别, 为让其执行必须翻译成机器语言

2. 高级程序转为机器语言做了什么

(1) 预处理

  • 展开头文件 / 宏替换 / 去掉注释 等等 (生成 .i 文件)
① 头文件
  • 包含函数声明、宏定义、数据类型、全局变量声明等内容
Ⅰ. 为什么要用头文件
  • 将多次使用的代码写在头文件里, 需要的时候直接调用, 节省开发时间

  • 编译器会将头文件内容拷贝一份, 后续调用的函数则有了来源, 才能通过编译

Ⅱ. 全局变量是干嘛的?
  • 多处代码需要用到同一个变量, 将其声明成全局变量写进头文件, 需要的时候直接调用, 降低代码量
Ⅲ. 注意事项
  • <stdio.h>

    • 用 < > 包起来的 .h 头文件是 C语言、C++ 标准库自带的
  • "test.h"

    • 用 " " 包起来的 .h 头文件是自编写的头文件
  • 学习 C++ 的要特别注意:

    • C++有万能头文件, 但其并非标准库自带的, 有的编译器能用, 有的不行, 为保证程序能正常运行, 尽量使用自带的
② 宏
  • define : C、C++关键字, 用于定义宏

  • #define Hello "Hello, World!"

    • 类似这种用一个标识符 (Hello) 来表示一个字符串 ("Hello, World!"), 就称为宏

    • 宏的标识符则称为宏名

Ⅰ. 为什么要用 define 定义宏
  • 增强代码可读性和减少代码量
Ⅱ. 怎么定义宏
  • #define 宏名 替换文本

    • 替换文本: 可以是任何常数、表达式、字符串等
  • 示例:

    • #define MAX 20

    • #define MAX(x,y) ((x) > (y) ? (x) : (y))

      • 将一些简短函数以表达式形式写出, 方便引用 (很少用)
    • #define ll long long

      • 给数据类型起一个别名

(2) 编译

  • 检查语法 (看有没有错误), 生成汇编代码 (生成 .s 文件)

(3) 汇编

  • 将汇编代码转化成二进制的机器码 (生成 .o 文件)

(4) 链接

  • .o 文件链接合成可执行程序

二. 结构体

1. typedef

  • typedef : C、C++关键字

(1) 用途

  • 为现有的数据类型起别名

  • 增强代码可读性和减少代码量

(2) 用法

  • typedef 原数据类型 新数据类型;

    • typedef long long ll;

(3) 注意

  • 用途有且只有为数据类型起别名, 功能没有宏定义强大

    • 故而常用于结构体
  • 与宏定义不同, 前面是要修改的, 后面是修改结果

2. 结构体定义

struct Books{char a[10];int b;
}

(1) 使用

  • C语言: struct Books c;

  • C++: Books c;

  • 因此在C语言中为方便写代码, 为结构体起一个别名方便编写程序

typedef struct BOOks{char a[10];int b;
}Book;
  • 后续使用: Book c;

(2) 等价

typedef struct Books{int a;char b;int c;
}* Book;
  • Book x; == struct Books* x

    • x 是一个指向 struct Books 结构体的指针变量
  • Book* y; == struct Books** y

    • y 是一个指向 struct Books 指针的指针变量 (二级指针)

以上一种容易理解错的写法, 以下是更好的写法


typedef struct Books{int a;char b;int c;
} Book;
  • Book* x == struct Books* x

  • Book** y == struct Books** y

三. 全局变量和局部变量

1. 变量名

  • 程序中局部变量和全局变量名称可以相同 (尽量不要这么干!!!)

  • 在一个函数内, 如果名字相同, 会使用局部变量, 不使用全局变量

2. 参数

  • 函数参数 (形参) 会被当成函数内的局部变量, 如果全局变量与其同名, 也是使用函数参数

    • void func(int x), x 就是函数参数 (形参)

3. 初始化

  • 局部变量定义后不会被系统自动初始化, 需手动初始化

  • 全局变量定义后会被系统自动初始化 (设为默认值 0)

    • 不同类型全局变量显示: 整数为 0 、字符为 '\0' 、指针为 NULL

以上变量知识代码示例:

int x = 100;void func(int x){printf("\n函数内形参与全局变量同名, 使用形参 x . x = %d\n", x);x = 50;printf("\n函数内修改值修改的是形参 x 的值, x = %d\n", x);
}int main(){printf("\nmain函数里是全局变量 x , 因为函数内无同名的. x = %d\n", x);func(10);return 0;
}
--------------------------------------------------------------------
// 以下是部分类型全局变量初值
int test_int;
char test_char;
double test_double;
int *test_ptr;
int test_array[3];int main(){printf("test_int: %d\n", test_int);printf("test_char: %d\n", test_char);printf("test_double: %f\n", test_double);printf("test_ptr: %s\n", test_ptr == NULL ? "NULL" : "non-NULL");for (int i = 0; i < 3; i++){printf("test_array %d: %d\n", i, test_array[i]);}printf("\n");return 0;
}

四. 常量

1. 定义与使用

  • 常量是一个固定值, 在程序运行过程中不会改变

  • 固定值又称字面量

  • 使用 #defineconst 声明

2. 示例

#define MAX 20const int a = 5;// 错误写法
const int a; //常量必须定义就赋值const int a;
a = 5; // 也不行,常量必须定义就赋值!!!

五. 进制转换

1. 十进制转二进制

  • 使用短除法一直除以2, 直到商1
  • 商1后以倒着的形式写出二进制结果
  • 十进制: 11 二进制: 1011

2. 十进制转任意进制

  • 假设十进制要转成 R 进制

  • 使用短除法一直除以 R , 直到商1

  • 商1后以倒着的形式写出 R 进制结果

3. 十进制转十六进制

(1) 十六进制每一位的数字

  • 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

  • 数字 10 ~ 15A ~ F 替换, 以方便表示

(2) 十六进制表示方法

  • 十六进制需加上 0x 前缀来表示 (常见)

    • 0xD : 十六进制的13
  • 后缀表示 (少见) : DH

    • 0xD 等价, 但是是添加的后缀 H

(3) 转换方法

  • 使用短除法一直除以16, 直到商1或商0

  • 商1后以倒着的形式写出十六进制结果

5835760d235719cb107bbbc7dbd0424d5988ad0a

  • 十进制: 100 十六进制: 64 (0x64)

4. 二进制转十进制

  • 将二进制 110101 转十进制

  • 方法: 将每一位乘以 2 的 n 次方 (n是位数 - 1)

    • 1 * 2^5 + 1 * 2^4 + 0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0

    • 32 + 16 + 0 + 4 + 0 + 1 = 53

5. 任意进制转十进制

  • 假设有 R 进制 转十进制

  • 方法: 将每一位乘以 R 的 n 次方 (n是位数 - 1)

    • 以十六进制举例: 0xD ⭢ D * 16^0 = 13 * 1 = 13

6. 二进制转十六进制

  • 将二进制 110101 转十六进制

  • 方法: 将二进制每四位隔开, 不足四位前面补0, 然后把四位二进制全转成十进制后拼起来

    • 110101 ⭢ 0011 | 0101 ⭢ 3 | 5 ⭢ 0x35

    • 验证: 3 * 16^1 + 5 * 16^0 = 48 + 5 = 53

7. 十六进制转二进制

  • 将十六进制 0xD 转二进制

  • 方法: 将每一位转二进制然后拼起来

    • 0xD ⭢ 13 ⭢ 0011 | 0101 ⭢ 00110101 ⭢ 110101

8. 二进制转八进制

  • 将二进制 110101 转八进制

  • 方法: 将二进制每三位隔开, 不足三位前面补0, 然后把三位二进制全转成十进制后拼起来

    • 110101 ⭢ 110 | 101 ⭢ 6 | 5 ⭢ 65 ⭢ 065 (八进制前缀为 0 )

常用的20个数字的各个进制表示法

29447ff752e57663b98fe9cb78a7d1f2d769f78b


六. 原码、反码、补码

二进制最高位为符号位 : 0 为正数, 1为负数

正数的原码、反码、补码都一样

1. 源码

  • 负数: -6

  • 二进制: 1000 0110

2. 反码

  • 二进制: 1111 1001

  • 在源码基础上除符号位都取反

3. 补码

计算机中最终存储的是补码

  • 二进制: 1111 1010

  • 在反码基础上加一

七. 运算符

1. 基础运算符

(1) 整除 /

① 特性
  • 向下取整

扩展:

  • 向下取整: 找到最大的小于等于它的整数 (1.3 取1 ; 5.6 取5)

  • 向上取整: 找到最小的大于等于它的整数 (1.3 取2 ; 5.6 取6)

  • floor() 向下取整, ceil() 向上取整, 需加上 <math.h> 头文件

② 示例代码
int a = 5 / 2;
printf("%d\n", a);

(2) 自增 ++

① 特性
  • ++ 在前先加一再输出

  • ++ 在后先输出再加一

② 示例代码
int b = 1;
printf("%d\n", ++b);
printf("%d\n", b++);
printf("%d\n", b);

(3) 自减 --

① 特性
  • -- 在前先减一再输出

  • -- 在后先输出再减一

② 示例代码
int c = 5;
printf("%d\n", --c);
printf("%d\n", c--);
printf("%d\n", c);

(4) 三目运算符 ? :

① 示例代码
int *test_ptr;
printf("test_ptr: %s\n", test_ptr == NULL ? "NULL" : "non-NULL");
② 解释
  • test_ptr 等于 NULL吗 ?

  • 等于 (真) 则输出冒号左边的 NULL

  • 不等于 (假) 则输出冒号右边的 non-NULL

2. 位操作符

(1) 左移 <<

① 原理
  • 假设十进制 6 左移一位

  • 首先将十进制 6 转为二进制 0110

  • 然后左移一位, 得到 1100

  • 再转成十进制, 结果为 12

② 特性
  • 左移直接对二进制进行操作, 更快

  • 左移一位相当于乘二

③ 示例代码
int d = 6;
d = d << 1;
printf("%d\n",d);

(2) 右移 >>

① 原理
  • 假设十进制 6 右移一位

  • 首先将十进制 6 转为二进制 0110

  • 然后右移一位, 得到 0011

  • 再转成十进制, 结果为 3

② 特性
  • 右移直接对二进制进行操作, 更快

  • 右移一位相当于除二 (向下取整)

③ 示例代码
int e = 6;
e = e >> 1;
printf("%d\n",e);

(3) 取反 ~

① 原理
  • 假设十进制 6 取反

  • 首先将十进制 6 转为二进制补码 0000 0110

  • 然后将每一位取反, 包括符号位, 得到 1111 1001

  • 再转成原码, 得到 1000 0111

  • 最后转成十进制, 结果为 -7

② 示例代码
int f = ~6;
printf("%d\n",f);

(4) 按位或、按位与、按位异或

① 原理
Ⅰ. 按位或 |
  • 十进制: 5 二进制: 0101

  • 十进制: 9 二进制: 1001

  • 按位或: 有一为一: 1101

Ⅱ. 按位与 &
  • 十进制: 5 二进制: 0101

  • 十进制: 9 二进制: 1001

  • 按位与: 都一为一: 0001

Ⅲ. 按位异或 ^
  • 十进制: 5 二进制: 0101

  • 十进制: 9 二进制: 1001

  • 按位异或: 不同为一: 1100

② 示例代码
int g = 5 | 9;
printf("%d\n", g);int h = 5 & 9;
printf("%d\n", h);int l = 5 ^ 9;
printf("%d\n", l);
③ 按位异或 特殊用法
  • 交换两个整数
int m = 10, o = 11;
m = m ^ o;
o = o ^ m;
m = m ^ o;printf("\n%d\n", m);
printf("\n%d\n", o);
http://www.hskmm.com/?act=detail&tid=38935

相关文章:

  • 「学习笔记」PHP 基础
  • 2025 建筑陶粒厂家最新推荐榜:回填 / 粘土 / 滤料 / 混凝土等多品类优选,实力企业权威测评推荐!
  • 251025
  • 2025 年最新地磅制造厂家推荐排行榜:聚焦品质创新服务,助力企业精准选优质地磅汽车衡 / 大型 / 可移动 / 100 吨 / SCS 型 / 自动称重地磅推荐
  • 关于我:新的开始,新的记录
  • 关于 NoiLinux 系统和 CodeBlocks 的考场使用
  • 2025 年知识库应用平台最新推荐排行榜!企业 / 个人 / 协同 / 智能等多场景适配,附权威测评与选择指南
  • 深入解析:深度学习调参指南:Batch Size的选择策略与实践
  • 2025 年最新推荐工作服实力厂家排行榜权威发布,助力企业精准挑选优质定制厂商商务 / 车间 / 企业 / 透气工作服厂家推荐
  • 2025年废水处理厂家权威推荐榜单:工业废水、生活污水处理设备及解决方案供应商深度解析
  • 2025年仿石漆厂家推荐排行榜,外墙仿石漆,内墙仿石漆,防霉仿石漆,水包水/水包砂仿石漆,耐污自洁仿石漆公司精选
  • 你的excel二级三级多级下拉菜单为啥不好用?讲清楚INDIRECT函数用法!
  • 权威调研榜单:航空警示球厂家TOP3榜单好评深度解析
  • 死锁 (Deadlock) 深度解析 - 详解
  • 解压小猫
  • 2025年家具厂家推荐排行榜:实木家具、定制家具、办公家具、软体家具、智能家具源头厂家精选
  • 2025 厨房排烟安装公司最新推荐榜:实力品牌服务与工艺解析及选择指南饭店/商用/罩/系统/厨房排烟管道专业服务公司推荐
  • 权威调研榜单:苏州吊车租赁公司TOP3榜单好评深度解析
  • 从零开始制作 MyOS(二)
  • 2025年高压加速老化设备厂家推荐排行榜,高压加速老化HAST,高压加速老化PCT,热流仪源头厂家专业测评与选购指南
  • 2025年摄像头防爆外壳供货商权威推荐榜单:监控摄像头外壳/摄像头外壳/路口警示道灯外壳源头厂家精选
  • 2025 液态硅胶设备源头厂家最新推荐榜:行业协会权威测评发布,品质与服务双维度精选
  • 2025 年阳台光伏厂家最新推荐排行榜:权威测评解析逆变器、储能及光伏板优质企业阳台太阳能光伏/储能/发电/阳台光伏板优质厂家推荐
  • 2025年废气治理设备厂家推荐排行榜,废气处理设备,工业废气净化装置,有机废气处理系统公司精选
  • 2025 年钛白粉源头厂家最新推荐排行榜:高分子材料领域专家解析改性技术与行业应用案例
  • 2025 年泳池设备厂家推荐:Firsle 法思乐泳池水处理与海洋馆维生系统设备专业方案及一体化设备优势解析
  • 2025年托辊输送带直销厂家权威推荐榜单:输送机托辊/托辊设备/托辊配件源头厂家精选
  • 2025年提升机厂家权威推荐榜:自动提升机、垂直提升机、斗式提升机,高效输送设备源头厂家精选
  • 2025 年最新冲压油供应厂家权威榜单:聚焦空调加工适配性与免清洗技术,助力企业精准选品免清洗/铝翅片/定子转子/高速冲压油厂家推荐
  • 2025年企业数字化展厅定制厂家权威推荐榜单:企业数字展厅/企业创意展厅/企业智能展厅源头厂家精选