C++语言笔记
本质上没有任何区别。 只不过一般:.h文件是头文件,内含函数声明、宏定义、结构体定义等内容。它约定为.c的声明定义而已.c文件是程序文件,内含函数实现,变量定义等内容。而且是什么后缀也没有关系,只不过编译器会默认对某些后缀的文件采取某些动作。你可以强制编译器把任何后缀的文件都当作c文件来编。这样分开写成两个文件是一个良好的编程风格。而且,比方说 我在aaa.h里定义了一个函数的声明,然后我在aaa
.c与.h的真实解释
本质上没有任何区别。 只不过一般:
.h文件是头文件,内含函数声明、宏定义、结构体定义等内容。它约定为.c的声明定义而已
.c文件是程序文件,内含函数实现,变量定义等内容。而且是什么后缀也没有关系,只不过编译器会默认对某些后缀的文件采取某些动作。你可以强制编译器把任何后缀的文件都当作c文件来编。
这样分开写成两个文件是一个良好的编程风格。
而且,比方说 我在aaa.h里定义了一个函数的声明,然后我在aaa.h的同一个目录下建立aaa.c ,aaa.c里定义了这个函数的实现。 main在运行时就会找到这个定义了这个函数的aaa.c文件,即aaa.c并不需要包含语句,只需要包含.h即可。
从C编译器角度看,.h和.c皆是浮云,就是改名为.txt、.doc也没有大的分别。换句话说,就是.h和.c没啥必然联系。.h中一般放的是同名.c文件中定义的变量、数组、函数的声明,需要让.c外部使用的声明。这个声明有啥用?只是让需要用这些声明的地方方便引用。因为 #include "xx.h" 这个宏其实际意思就是把当前这一行删掉,把 xx.h 中的内容原封不动的插入在当前行的位置。由于想写这些函数声明的地方非常多(每一个调用 xx.c 中函数的地方,都要在使用前声明一下子),所以用 #include "xx.h" 这个宏就简化了许多行代码--让预处理器自己替换好了。也就是说,xx.h 其实只是让需要写 xx.c 中函数声明的地方调用(可以少写几行字),至于 include 这个 .h 文件是谁,是 .h 还是 .c,还是与这个 .h 同名的 .c,都没有任何必然关系。
这样你可能会说:啊?那我平时只想调用 xx.c 中的某个函数,却 include了 xx.h 文件,岂不是宏替换后出现了很多无用的声明?没错,确实引入了很多垃圾,但是它却省了你不少笔墨,并且整个版面也看起来清爽的多。鱼与熊掌不可得兼,就是这个道理。反正多些声明(.h一般只用来放声明,而放不定义)也无害处,又不会影响编译,何乐而不为呢?
(1)通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
(2)头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。
一些常识
1, 类的成员函数的参数初始化默认值时,.h申明里或.cpp定义函数里此2处只可以一个地方写 默认值,但一般在.h的申明里写.
2, 类里面的私有成员变量或函数,只能在用类里面函数去访问.
3, 类 对象2(对象1) , 类 对象2=对象1 :它们都是调用类的拷贝函数实现对象复制.
而对象p2 =p1 :它们是已有对象,调用类的运算函数
4, 对象.成员: 用"."访问对象的成员; 对象指针->成员: 用"->"访问对象指针的成员.
5, int& x = x1: 引用,一变量多个名而已;(注:此&跟取地址没有任何关系,c++ 一符多义而已)
int* x = &x1: 取址,取已有变量的地址.
6,
7,
8,
以下是单片机的C/++
bit sbit sfr的区别
1.bit 和 sbit 都是 C51 扩展的变量类型。
bit 和 int char 之类的差不多,只不过 char=8 位, bit=1 位而已。都是变量,编译器在编译过程中分配地址。除非你指定,否则这个地址是随机的。
这个地址是整个可寻址空间,RAM+FLASH+扩展空间。bit 只有 0 和 1 两种值。
sbit 是对应可位寻址空间的一个位,可位寻址区:20H~2FH。一旦用了 sbit xxx = REGE^6 这样的定义,这个 sbit 量就确定地址了。sbit 大部分是
用在寄存器中的,方便对寄存器的某位进行操作的。
3.sfr 特殊功能寄存器
sfr 也是一种扩充数据类型,点用一个内存单元,值域为 0~255。利用它可以访问 51 单片机内部的所有特殊功能寄存器。如用 sfr P1 = 0x90 这一句
定 P1 为 P1 端口在片内的寄存器,在后面的语句中我们用以用 P1 = 255(对 P1端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。
sfr 是定义 8 位的特殊功能寄存器.
sfr16 则是用来定义 16 位特殊功能寄存器,
如 8052 的 T2 定时器,可以定义为:sfr16 T2 = 0xCC; //这里定义 8052 定时器 2,地址为 T2L=CCH,T2H=CDH
用 sfr16 定义 16 位特殊功能寄存器时,等号后面是它的低位地址,高位地址一定要位于物理低位地址之上.注意的是不能用于定时器 0 和 1 的定义.
sbit 的用法有三种:
第一种方法:sbit 位变量名=地址值
第二种方法:sbit 位变量名=SFR 名称^变量位地址值
第三种方法:sbit 位变量名=SFR 地址值^变量位地址值
data 表明数据在片内数据存储区;
xdata 表明数据在片外数据存储区;
code 表明数据在程序存储区;
extern 定义的数据是在另外一个模块,当引用其它文件中的变量时要加上 extern。extern的重要意义在于表明要定义的数据已经在其他地方定义过, 此处只是引用, 所以编译器不会另外开辟内存。
unsigned 定义无符号变量 i
这时如果循环 for ( i=8; i >=0; i--) 永远为真,
因为无符号0后就是255或其它,没有负值,永远>=0了.
volatile限定符
volatile 的关键在于处理编译器不可见的修改,而不是程序本身显式的修改。
volatile只保证每次访问都从内存读取/写入告诉编译器:任何地方修改我都知道.
| 情况 | 是否需要 volatile |
原因 |
|---|---|---|
| 变量只在当前线程/函数内修改 | 不需要 | 编译器能看到所有修改 |
| 变量可能被中断/其他线程/硬件修改 | 需要 | 编译器不知道这些外部修改 |
| 变量是内存映射的硬件寄存器 | 需要 | 硬件可能随时改变寄存器值 |
| 变量在多线程间共享(仅用volatile不够) | 需要但不足 | 还需要原子操作或内存屏障 |
注:我的ESP32 S3实验时有volatile限定符有没有结果都一样,但还是要写上.
内存空间分类
| 内存区域 | 分配 / 释放方式 | 典型存储内容 | 生命周期 |
|---|---|---|---|
| 代码段 | 编译时确定,程序启动时加载 | 可执行指令 | 整个程序运行期 |
| 数据段 / BSS 段 | 编译时确定,程序启动时分配 | 全局变量、静态变量 | 整个程序运行期 |
| 栈 | 函数调用时自动分配,返回时释放 | 局部变量、函数参数、调用上下文 | 函数调用期间 |
| 堆 | 手动malloc/free(c)或new/delete(c++)申请/释放 |
动态分配的数组、结构体等 | 分配到释放(手控) |
更多推荐


所有评论(0)