一、关键字
1.Continue
continue 的作用是跳过本次循环体中余下尚未执行的语句,立即进行下一次的循环条件判定,可以理解为仅结束本次循环。
注意:continue 语句并没有使整个循环终止。且只能在循环语句中使用。
2. Break
只能用于循环语句或者开关语句会使最近包含 break 语句跳出,在while for循环中 跳出本层循环,在 swich-case 中跳出对应的 case,在 swich-case 语句中如果没有 break 语句那么就 一定会执行下面的语句。
如果 for(){switch case: break},for 循环不受影响。
break 语句用在循环体中,可结束本层循环,continue 语句用在循环体中,可结束本次循环。
3.Return
结束当前循环,退出函数,用在函数体中,返回特定值。
4.Volatile(编译优化阶段)
作用:告诉编译器该变量是容易发生变化的,不能对该变量进行优化,每次取值 都必须从内存中取值而不是直接去取之前在寄存器中的值。
例子: Volatile int a=20,b,c; b=a; c=a;
代码执行流程如下:
b = a;先从 a 的内存中取值存放到寄存器,再把寄存器的值给存到 b 的内存
c = a;把寄存器的值给存到 c 的内存
可以看出编译器对 c=a 这步进行优化,不再执行从 a 的内存中取值,而是直接从寄存器中取 值,如果这段时间内 a 的发生变化,那么 c 就不能得到最新的值,这个时候就需要使用 volatile 告诉编译器,不要对变量 a 优化,每次都是从内存中取 a 的值.
常见场景:
1)多线程使用共享变量:因为多线程是多核操作,同时进行
2)中断:中断程序会修改其他程序中使用的变量
3)硬件寄存器:因为寄存器随时会被修改,好比 AD 转换的寄存器,随时会 因 为电压变化而修改
4)外部任务会修改变量
5.Struct(结构体) (C 和 C++区别,求结构体大小,使用的注意事项)
1. 在 c 语言中结构体是不允许有函数,在 c++中可以;
2. C 语言结构体是不可以继承,c++可以继承;
3. C语言中结构体的使用必须要用别名或者使用struct,不能直接使用例如
Struct student
{
Int age;
Int num;
Inr sex;
}
Typedef struct student {
Int age;
Int num;
Inr sex;
}student; //必须得别名才可以使
或者在使用的时候加上 struct,例如 struct student student;
4.访问权限不同 在 c 中默认是共有(public),不可以修改权限,在 c++中权限可以修改
5.初始化在 c 中不可以初始化数据成员,c++可以初始化
6.C++中空结构体大小为 1,C 为 0
7.class 和 struct 的区别?
1)继承权限:class 是默认 private,struct 是 public
2)访问权限:class 作为对象的实现体,默认是私有访问(private),而 struct 是作 为数据结构的实现体,是共有访问(public)
3) class 可以用于定义模板,而 struct 不能
8.Union(联合体)
联合体 union 和结构体 struct 的区别: 对于联合体所有的成员都共享一块内存,而结构体是所有变量内存的叠加, 需要考虑字节对齐问题,对于联合体来说,只要你修改里面的成员的数据就会修 改其他成员的数据,而结构体的成员数据是不影响的。
联合体一般可以用来判断大小端问题:
大端字节序:高字节存放在低位地址,低字节存放在高地址
小端字节序:低字节存放在低位,高字节存放在高位 使用联合体判断大小端问题:
大小端转换问题: 这里主要是位移操作 比如对于一个 32 位进行大小端转换:
思路: 把 0-7 位移动到 24-31 8-15 位移动到 16-23
16-23 位移动到 8-15 位 24-31 位移动到 0-7
计算占用空间大小问题: 对于不同位的操作系统,个别数据类型数据大小不一样, Long 和 unsigned long 在 32 位中是 4 个字节 在 64 位中是 8 个字节 计算的时候需要考虑字节对齐问题: 1. 所占空间必须是成员变量中字节最大的整数倍
2. 每个变量类型的偏移量必须是该变量类型的整数倍
3. 对于联合体,由于所有变量都是共用一块内存,还需注意数组占用最大内存
例如: Typedef union { double I; int k[5]; char c;} DATE;
在联合体中成员变量最大为 double 为 8 个字节,所以最终大小必须是 8 的整数倍;又因为联合体是共占内存空间,即 int*5=20 字节,所以最终为 24 个字节。
Typedef struct data { int cat; DATE cow; double dog;} too; 求 sizeof(too); 解:在结构体里面联合体为 24,联合体的最大类型为 8 字节,所以联合体 的起始位置必须满足偏移量为 8 的倍数,计算如下:
Cat:1-4, DATE cow: 8+24 Double dog :32+8=40
最终的大小得是结构体中的类型的最大长度的整数倍
除了结构体中的联合体外,其他类型的偏移量必须是该类型的整数倍
如果里面有联合体,该联合体的起始位置要满足该联合体的里面的最大长度类型的偏移量
9.Enum
枚举变量的默认值为前一个变量的值加一,若第一个枚举变量没被赋值,则其默认值为0。
此外枚举变脸值是可以重复的。
10.Typedef
1.#define和typedef的区别 (宏,关键字,预处理,编译,检查)
#define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。
typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。
注意#define和typedef定义指针的区别
#define myptr int* p
myptr a,b; //a是int * a, b是 int b
typedef int* myptr;
myptr a,b; //a是int * a, b是 int* b
补充:int *p,q表示p是指针变量,q是int变量
typedef int (*function)() //表示函数指针,重新命名为funtion
11.Const (C中的变量:局部,函数形成,返回值,指针,typedef的区别,数组大小定义,case C++:常函数,常对象)
- 定义变量,表示该变量是个常量,不允许修改
例如:const int a=100;
错误:a=200;
- 修饰函数参数,表示函数体内不能修改该参数的值
- 修饰函数的返回值 const char getstr()
- const修饰的常见:
Const int a; int const a;是一样的,都是修饰变量a为常量
Const * int a ; int const *a ; 修饰的是这个指针指向的内容不允许修改,这个指针的地址可以改变 常量指针
Int * Const a; 修饰的指针,表示这个指针的地址不可以修改,地址的内容可以修改 指针常量
Const int * const a; 表示指针的地址不可以修改,内容也不可以修改
4.const修饰函数在c++的类中是不能Virtua虚函数
5.在C++类中有常函数的概念,比如在类中定义如下函数:
Void fun() const { }:像这种就是常函数,这种函数只能读取类中数据,不能修改
60const 修饰的变量存放位置
对于const修饰的局部变量:存放在栈中,代码结束就会释放,在C语言中可以通过指针修改里面的值
对于const修饰的全局变量(已初始化的)存放在只读数据段,不可以通过指针修改里面的值,未出示化的存放在.bss
12.Extern (链接阶段)
1.声明外部变量:(保存在数据段)
在文件a.c定义和声明变量a,int a=20; //这里会建立存储空间
通过extern 在b.c文件里面声明a之后就可以使用,记住不能初始化
注意:如果想要定义一个变量被其他文件使用,即定义一个全局变量,这个变量不能定义在头文件里面,然后在需要调用该变量的.c文件里面extern声明该变量是不可以的,编译期会报错:multiple define 多个定义,
正确做法如下:
在main.c文件里面定义变量int goble为全局变量,
在fun.c文件里面extern int goble;即可
该作用主要是告诉编译器我在其他文件定义了变量a,并且分配了空间,不再为该变量申请空间
2.声明外部外部函数声明外部一样
3.Extern “C” : 该做用是实现在c++中调用c语言代码,告诉编译器这部分代码要是有C编译
二、代码随想录 (续数组理论)
69. x 的平方根 难度简单
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
633. 平方数之和
难度 中等
给定一个非负整数 c
,你要判断是否存在两个整数 a
和 b
,使得 a2 + b2 = c
。
三、移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
#暴力解法
这个题目暴力的解法就是两层for循环,一个for循环遍历数组元素 ,第二个for循环更新数组。
#双指针法
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。
- 时间复杂度:O(n)
- 空间复杂度:O(1)
27. 移除元素 难度:简单
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
相关题目推荐
- 26.删除排序数组中的重复项
- 283.移动零
- 844.比较含退格的字符串
- 977.有序数组的平方
26. 删除有序数组中的重复项 难度 :简单
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:
更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。
80. 删除有序数组中的重复项 II 难度:中等
给你一个有序数组 nums
,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
283. 移动零 难度:简单
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
844. 比较含退格的字符串 难度 简单
给定 s
和 t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true
。#
代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
977. 有序数组的平方 难度 简单
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。