目录
一.运算符的优先级
二.数据类型转换
三.switch和if的选择
四.const int*p与int* const p 的区别
五.底层Const和顶层Const的区别
六.不安全函数
六.cin>> 返回值
七.getline返回值是cin
八.计算机英语加油站
九.goto语句
十.cmd
十一.VS播放音乐
十二.宽度与对其
十三.原地交换字符串
十四.终端
十五.string转char*类型
十六.静态库的创建
十七.使用一个循环给二维数组赋值
十八.断言
十九.什么是空指针?
二十.指针与指针相减
二十一.const和指针
二十二.查看变量类型的函数
二十三.C++类中的默认构造函数显示声明
二十四.输入密码时候,隐藏密码
二十五.解决多文件开发头文件重复包含的方法
二十六.指针数组与数组指针
二十七.void空指针
二十八.函数指针
二十九.引用类型
三十.指针引用
三十一.内存复制函数
三十二.函数的栈空间(避免栈空间溢出)
总结:
对知识的查漏补缺
- 个人主页:北·海
- CSDN新晋作者
- 欢迎 点赞✍评论⭐收藏
- ✨收录专栏:C/C++
- 希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!
一共15个级别
int i =0;
int t = 2;
const int *p = &i;//可以改变p的指向,但是不能通过*p改变指向变量的值
int* const p1 = &i;//可以通过*p改变指向变量的值,但是不能在指向其他变量了
//*p = 3;//error
//p = &t;//pass
//*p1 =3;//pass
//p1 = &t;error
顶层const,指针本身是常量
int x;
scanf_s("%d",&x);//不需要使用第三个参数,用法和scanf相同
float f;
scanf_s("%f",&f);//不需要使用第三个参数,用法和scanf相同
char c;
scanf_s("%c",&c,sizeof(c));//需要使用第三个参数,否则有警告
char name[16];
scnaf_s("%s",name,sizeof(name));//需要使用第三个参数
int age;
char name[16];
scanf_s("%d%s",&age,name,sizeof(name));
char line[32];
gets_s(line,sizeof(line));
if(!(cin>>word)){}//方法1
if((bool)(cin>>word) == 0){}//方法2
getline(cin, word) >> count;
if(getline(cin,line)==0){}//错误,不能通过编译
string ret;
for(int i = 0;i<5;i++){
cout<<"开始第"<>ret;
if(ret != "yes") continue;
else{
cout<<"我中意你,你中意我吗?"<>ret;
if(ret == "yes"){
goto happy;
}
}
}
happy :
cout<<"幸福生活"<
- goto在应用开发中不建议用,会破坏程序的结构性,一般用在底层开发,追求效率
- 语法 :goto 标志; 标志:
- goto在应用开发中一般将标志后面的语句封装为函数,进行函数调用 ; 或者用flag进行标记,标记成立执行标志后的代码
- 标签必须和goto 标志;必须放在同一个函数内,不能跨函数,但是可以在同一个函数的任何位置
十.cmd
- 切换盘 直接 d:或者c:
- 进入某个文件,用cd 例如 cd d:\ceshi,就会进入d盘下的ceshi目录
- 查看编码用chcp(活动码)
- 修改编码用: chcp 编码 ,例如 chcp 936,会改为936编码
- 在一个目录下放两个exe文件,利用破解.exe | 客户.exe,会将前面程序的输出数据,通过管道作为后面文件的输入数据
- 利用dir查看目录下面的文件
十一.VS播放音乐
- 头文件
#include
#prama comment(lib,"winmm.lib")
- 加载音乐代码
mciSendString(_T("play 音乐地址 repeat"),0,0,0);
- _T可以用多字符集替代
- play 播放
- repeat 重复
十二.宽度与对其
- c++中的设置文本宽度头文件为#include
,语句为setw(宽度)
- 设置对其 : 例如左对齐 std::left
十三.原地交换字符串
- 当left = right时,没有必要再交换,也可也用于交换其他数据类型
string str;
int left,right;
cout<<"输入一个字符串: ";
cin>>str;
left = 0;
right = str.length()-1;
while (left
十四.终端
- 控制终端大小
- mode con cols = 列数,lines =行数
- system("任何终端命令");,再system里面可以写任何终端命令进行执行
- 例如 : system("mode con cols=40 lines=15");
十五.string转char*类型
- 函数c_str()函数可以将string类型转换为从const char*类型
using namespace std;
void print(const char * str){
cout<
十六.静态库的创建
- 在项目属性c/c++里面,选用无预编译头,创建头文件与cpp文件,需要注意release模式下还是debug模式,在用库时候要与该模式相匹配,库的函数实现是外界无法看到的,最后在要使用的项目里面导入.h文件和.lib文件
十七.使用一个循环给二维数组赋值
- 行数 : 第几个元素 / 原列数
- 行数 : 第几个元素 % 原列数
int nums[3][4];
for(int i = 0 ;i<12;i++){
nums[i/4][i%4] = i+1;
}
十八.断言
- 程序的接口传入进去的数据可能是非法的,要想当传进去的值为非法值时候,给出提示,可以使用断言
- 对非预期错误使用断言
- 空指针
- 输入或输出参数的值不在预期范围内
- 数组的越界
- 如果断言的条件返回错误,则终止程序执行
- 头文件 #include
- 原型定义
- void assret(int expression);
- 语句 assert(数据正常时候的条件)
十九.什么是空指针?
- 空指针,就是值为零的指针,(任何程序数据都不会存储在地址为0的内存块中,他是被操作系统预留的内存块,是不能访问的),int *p =NULL;
- 初始化为空指针,避免访问非法数据
- 指针不在使用时,可以设置为空指针
- 表示这个指针还没有具体的指向,使用前进行合法性判断
int *p =NULL;
if(p){
//指针不为空,对指针进行操作
}
二十.指针与指针相减
- 指针的相加是不行的,被禁止的
- 指针与指针做减法适用的场合,两个指针都指向同一个数组,相减的结果为两个指针之间的元素数目,而不是两个指针之间相差的字节数
- 如果两个指针指向不同数组,则相减的结果是相差的字节数,但是这样的相减没有意义
- 不同类型的指针不允许相减
二十一.const和指针
- const 写在int之前,则限定不能通过*指针去改变该指针指向的值,但是可以指向别的指针
- const 写在int之后,则限定可以通过*指针去改变该指针指向的值,但是不能指向别的指针
- 两个const一个写在int前,一个写在变量名前,限制指针不能指向别的指针,并且不允许修改指针指向的值
- 总结 : 看const离类型(int)近,还是理变量名近,离谁近,就修饰谁,谁就不能变
#include
using namespace std;
int main() {
int wife = 30;
int girl = 18;
//第一种 : 渣男型,普通指针可以随意更改指向与指向地址的值
int* zha_nan = &wife;
cout << *zha_nan << endl;
zha_nan = &girl;
cout << *zha_nan << endl;
//第二种 : 直男型,以自我为中心,可以改变指向,但是不可以改变指向的地址的值
const int* zhi_nan = &wife;
//*zhi_nan = 25;//报错,不能改变值
zhi_nan = &girl;
cout << *zhi_nan << endl;
//第三种 : 暖男型,专一,不可以改变指向,但是可以改变指向的地址的值
int* const nuan_nan = &wife;
//nuan_nan = &girl;//报错,不能改变指向
*nuan_nan = 25;
cout << *nuan_nan << endl;
//第四种 : 超级暖男型,超级专一,不能改变指向,也不能改变指向地址的值
const int* const _super_nuan_nan = &wife;
//*_super_nuan_nan = 25;//报错,不能改变指向地址的值
//super_nuan_nan = &girl;//报错,不能改变指向
//总结 : const理谁近就修饰谁,理(int)近,则修饰该指针的值不能改变,修饰变量,
// 则该指针不能在指向别的变量了
}
二十二.查看变量类型的函数
- 头文件 #include
- 语法 : typeif(变量名).name()
#include
#include
using namespace std;
int main() {
int i = 10;
int* k = &i;
cout << typeid(k).name()<< endl;
}
二十三.C++类中的默认构造函数显示声明
- 显示声明方式 : 类名 () = default;
- 作用,如果没有显示声明,类中如果没有其他构造函数的话,系统会默认声明默认构造函数,如果显示声明了,系统则不会声明默认构造函数,但是当加上该语法之后,即使类中有其他构造函数,系统仍然会声明一个默认的构造函数
- 需要注意的是,
salary_data()
的定义应该在类的声明中进行,并且必须是构造函数的声明之一。在类声明中可使用 = default
,但在类的定义(实现)中则不能使用 = default
。在类定义中,如果没有显式提供构造函数的实现,编译器会自动生成默认构造函数的实现。
二十四.输入密码时候,隐藏密码
- 用函数getch(),头文件#include
- 输入一个字符时候不会回显,getc会回显
- 实现思路: 输入一个字符,由于不知道密码长度,所以设置为死循环,如果不是回车键,即将该字符添加到存放密码的数组里,顺便打印一个星号,如果输入的为回车键,由于getch()函数读入回车键时候,返回的是\r,所以如果是\r,则将字符数组的末尾加上\0,再跳出循环
//密码输入
void Input_pwd(char* pwd,int size) {
char c = 0;
int i = 0;
while (1) {
c = getch();//不会回显
if (c == '\r') {//getch函数读到回车符号为\r
pwd[i] = '\0';
break;
}
else {
cout << '*';
pwd[i++] = c;
}
}
cout << endl;
}
二十五.解决多文件开发头文件重复包含的方法
- 由于使用多文件开发,需要再cpp文件里面包含.h文件,再将多个.h文件相互包含,可能会出现重复包含的情况,
- 解决方法 : VS里面特定的方式是,在.h文件的开头加上 #pragma once
- 公用方法 :在.h文件里面用宏定义,
#例如在cs.h文件内,宏名一般用该格式,没要求
#ifndef _CS_H_
#define
//代码块
#endif//对应的是ifndefine
二十六.指针数组与数组指针
- 数组指针 例如 int (*p)[3];
- 数组指针访问方法 ( p = &A[0] )
- 数组法 : (*p)[j];
- 指针法 : *((*p)+j) *( *(p + i) + j)
- 指针数组 例如 int *p[3];.每个元素都是一个变量的地址
二十七.void空指针
- 其他类型可以自动转换为void类型,但是void类型要转换成其他类型需要强制类型转换
- 空指针不允许进行算术运算,因为大小不知道
- 空指针里面仍然存储的是变量的地址,只是类型不知道
int a = 10;
int *p1 = &a;
void* p = &a;
//cout << *p << endl; error 空指针
//p1 = p;//error
p1 = (int *)p;//需要进行强制类型转换
p = p1;//可以,其他类型可以转换为空指针
二十八.函数指针
- 函数指针的定义 : 把函数声明移过来,把函数名改为(* 函数指针名)
例如
//函数
int compare_int (const int *,const int *);
//该函数的指针
int (*fp) (const int *,const int *);
//给该指针赋值
fp = &compare_int;
//传参数两种方式
(*fp)(&x,&y);//第一种,按普通指针解引的方式进行调用
fp(&x,&y);//第二种,直接调用
//(*fp)等同于compare_int
- qsort()函数
- 语法 qsort(数组名,数组元素个数,每个元素占的字节,cmp函数);
- qsort参数为void类型指针,可以比较任何数据类型
- cmp函数格式
int cmp(const void *a, const void *b) {
return *(int*)a - *(int*)b ;//由小到大排序
//换成b-a之后是从大到小排列
}
- 测试 :
int cmp(const void *a, const void *b) {
return *(int*)b - *(int*)a ;
}
int main() {
int q[2] = { 1,2 };
qsort(q, sizeof(q) / sizeof(int), sizeof(int), &cmp);
cout << q[0] << " " << q[1] << endl;
}
- 字符比较,混杂大小写,在比较时候不考虑大小写的方法
二十九.引用类型
- 引用变量本身也会占内存,内存的大小等于一个指针变量的大小
- 对同一内存空间可以取好几个别名
- 引用可以定义多个,引用也有自己的空间,引用变量像常指针,编辑器在编译时会将引用改为指针
- 在c++的底层引用就是用指针实现的 Type& name <-----> Type* const name
- 在使用的角度,引用会让人误会是一个别名,没有自己的存储空间,这是c++为了实用性而做出的细节隐藏
#include
#include
using namespace std;
int swap1(int& a, int& b) {
int temp = a;
a = b;
b = temp;
return 0;
}
int swap2(int* const a, int* const b) {
int temp = *a;
*a = *b;
*b = temp;
return 0;
}
int main() {
int x = 10;
int y = 100;
swap1(x, y);
cout << "x = " << x << " y = " << y << endl;
swap2(&x, &y);
cout << "x = " << x << " y = " << y << endl;
}
//编辑器会将引用类型的swap1在编译时候转换成swap2的形式
三十.指针引用
-
可以代替二级指针
int home1(int ** meipo) {
static int boy = 18;
*meipo = &boy;
return 0;
}
int home2(int* & meipo) {
static int boy = 18;
meipo = &boy;
return 0;
}
int main() {
int* meipo = nullptr;
home1(&meipo);
cout << "meipo = " << *meipo << endl;
//指针引用,可以代替二级指针,
home2(meipo);
cout << "meipo = " << *meipo << endl;
return 0;
}
三十一.内存复制函数
- 将一段内存里面的数据复制到另一段内存种
memcpy(&b,&a,sizeof(a));
//将a变量内存,复制给b内存一份,大小为a变量的大小
三十二.函数的栈空间(避免栈空间溢出)
- 错误1 当数组的内存占用较大时,会引发异常
#include
using namespace std;
int main() {
char buff[2000000];
cout << (int)buff[sizeof(buff) - 1] << endl;

- 错误 2
- 当调用次数较小的时候,栈内存还没有满,可以输出,该地址相减除以1024等于100,就是每调用一次函数,分配的内存数,

- 当调用函数次数较大时候,栈内存爆掉了,就会引发异常
- 当n=20时候

- 内联函数inline:
- 可以解决该函数调用时间上的问题,可以缩短调用时间
- 但是会将主调函数编译后的代码块变得十分 "臃肿"
- inline定义的函数,在编译时,会将该函数的函数体直接插入到调用处
- 就相当于内联函数的函数体在调用出重新写了一遍
总结:
- 栈的内存默认为2兆,内存可以修改
- 站内存储的是非new或molloc出来的变量,没调用一次函数,就会在栈内开辟一段空间,大小为该函数内所有变量的内存和,当内存过大时,栈爆掉就会引发异常
- 程序是从高内存向低内存进行存储的,两个相邻空间的内存地址相减就能得到
- 每分配一块空间,这块内存空间就叫做 " 栈帧 "
你可能感兴趣的:(C++,C语言,c++,c语言,开发语言)