C++学习笔记之基础语法
基础语法
switch和if区别
先看一下switch和if汇编代码的区别:
int a = 3;
00007FF6A1831B4C mov dword ptr [a],3
if (a == 1)
00007FF6A1831B56 cmp dword ptr [a],1
00007FF6A1831B5D jne main+164h (07FF6A1831B74h)
{
cout << a;
00007FF6A1831B5F mov edx,dword ptr [a]
00007FF6A1831B65 mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831B6C call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
00007FF6A1831B72 jmp main+195h (07FF6A1831BA5h)
}
else if (a == 2)
00007FF6A1831B74 cmp dword ptr [a],2
00007FF6A1831B7B jne main+182h (07FF6A1831B92h)
{
cout << a;
00007FF6A1831B7D mov edx,dword ptr [a]
00007FF6A1831B83 mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831B8A call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
}
else
00007FF6A1831B90 jmp main+195h (07FF6A1831BA5h)
{
cout << a;
00007FF6A1831B92 mov edx,dword ptr [a]
00007FF6A1831B98 mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831B9F call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
}
switch (a)
00007FF6A1831BA5 mov eax,dword ptr [a]
00007FF6A1831BAB mov dword ptr [rbp+154h],eax
00007FF6A1831BB1 cmp dword ptr [rbp+154h],1
00007FF6A1831BB8 je main+1B5h (07FF6A1831BC5h)
00007FF6A1831BBA cmp dword ptr [rbp+154h],2
00007FF6A1831BC1 je main+1CAh (07FF6A1831BDAh)
00007FF6A1831BC3 jmp main+1DFh (07FF6A1831BEFh)
{
case 1:
cout << a;
00007FF6A1831BC5 mov edx,dword ptr [a]
00007FF6A1831BCB mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831BD2 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
break;
00007FF6A1831BD8 jmp main+1F2h (07FF6A1831C02h)
case 2:
cout << a;
00007FF6A1831BDA mov edx,dword ptr [a]
00007FF6A1831BE0 mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831BE7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
break;
00007FF6A1831BED jmp main+1F2h (07FF6A1831C02h)
default:
cout << a;
00007FF6A1831BEF mov edx,dword ptr [a]
00007FF6A1831BF5 mov rcx,qword ptr [__imp_std::cout (07FF6A1841150h)]
00007FF6A1831BFC call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF6A18411E0h)]
break;
}
从上面的代码可以看出,正常情况下switch和if的性能没什么区别:
- if按顺序执行判断,如果条件满足则执行对应的语句并退出条件判断;如果条件不满足则跳过对应的语句,执行下一个条件判断。
- switch先判断所有条件,如果条件满足则跳转到对应的语句,执行语句,直到遇到break时退出。
其实,编译器实现switch语句有三种方式:逐条件判断、跳转表、二分查找法,具体情况参考C++性能switch语句
枚举定义及作用域
枚举使用时注意作用域的问题:
enum MONTH // 不限定作用域
{
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE,
JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER
};
const int NOVEMBER = 1; //重定义错误
上面的代码会由于枚举作用域的问题出现重定义错误,参考 C++11 Enum枚举使用心得 使用限定作用域的枚举类型:
enum class DAY // 限定作用域
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
FRIDAY, SATURDAY, SUNDAY
};
DAY day = DAY::SUNDAY; // OK
int day = DAY::SUNDAY; //错误,限定作用域的枚举类型无法通过隐式转换到其他类型
注:由于枚举成员是const,因此建议用定义枚举成员用大写。
结构体数据耐齐--缺省对齐原则
字节对齐的细节和具体编译器实现相关,参考32、64位编译器各类型大小和字节对齐,一般满足三个准则:
- 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
- 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节;
- 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。
结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。
struct S1
{
char x;
int z;
short y;
};
struct S2
{
char x;
short y;
int z;
};
cout << sizeof(S1) << endl; // 12
cout << sizeof(S2) << endl; // 8
在编码时,可以动态修改字节对齐方式,参考关于字节对齐、设置编译器的内存对齐方式(C++):
Visual C++:
- 使用伪指令#pragma pack (n),编译器将按照n个字节对齐。
- 使用伪指令#pragma pack (),取消自定义字节对齐方式。
g++:
- __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
- attribute ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。
函数重载overload与C++Name Mangling
可以使用undname工具查看函数的真实名称,代码如下:
int test(int a)
{
return a;
}
int test(double a)
{
return int(a);
}
使用Notepad++打开编译后的obj文件,搜索“test”得到如下内容:
?test@@YAHH@Z
?test@@YAHN@Z
在cmd中进入undname.exe所在的路径(系统内会有多个undname.exe,根据IDE的情况选择即可),我使用的是下面的路径:
cd C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\bin\Hostx86\x64\
调用undname.exe,输入以下命令:
undname ?test@@YAHH@Z
得到函数的真实名称:
Undecoration of :- "?test@@YAHH@Z"
is :- "int __cdecl test(int)"
同理,可得到:
Undecoration of :- "?test@@YAHN@Z"
is :- "int __cdecl test(double)"
指向函数的指针与返回指针的函数
每一个函数都占用一段内存单元,它们有一个起始地址,指向函数入口地址的指针称为函数指针。
形式:数据类型(*指针变量名)(参数表);
举例:int (*p)(int);
与返回指针的函数之间区别:
- int (*p) (int); //是指针,指向一个函数入口地址
- int* p (int); //是函数,返回的值是一个指针
C++学习笔记之基础语法的更多相关文章
- Java学习笔记之---基础语法
Java学习笔记之---基础语法 一. Java中的命名规范 (一)包名 由多个单词组成时,所有字母小写(例如:onetwo) (二)类名和接口 由多个单词组成时,所有单词首字母大写(例如:OneTw ...
- 2020寒假学习笔记14------Python基础语法学习(三)
今天学习了Python的基础语法,其中学的内容有: 比较运算符.逻辑运算符.同一运算符.整数缓存问题.基本运算符.复合复制运算符.运算符优先级问题.字符串基本特点.字符串的编码.空字符串和len()函 ...
- Hive学习笔记:基础语法
Hive基础语法 1.创建表 – 用户表 CREATE [EXTERNAL外部表] TABLE [IF NOT EXISTS 是否存在] HUserInfo ( userid int comment ...
- 【C语言C++编程学习笔记】基础语法,第一个简单的实例编程入门教程!
C语言/C++编程学习:一个简单的实例 让我们来看一个简单的C语言程序.从下面的程序可以看出编写C语言程序的一些基本特征. 如果你能知道该程序将会在显示器上显示一些内容,那说明你还是知道一些的! ...
- PHP学习笔记01——基础语法
<!DOCTYPE html> <html> <?php // 1.使用$加变量名来表示变量,php是弱类型语言,不要求在使用变量前声明,第一次赋值时变量才被创建 $a ...
- 01-Python学习笔记-基础语法
Python标识符 -d 在解析时显示调试信息 -O 生成优化代码 ( .pyo 文件 ) -S 启动时不引入查找Python路径的位置 - ...
- java学习笔记之基础语法(一)
1.java语言基础由关键字.标识符.注释.常量和变量.运算符.语句.函数和数组等组成. 2.1关键字 定义:被java语言赋予了特殊含义的单词 特点:关键字中所有的字母都是小写. 2.2用于定义数据 ...
- Java学习笔记之基础语法(顺序,条件,循环语句)
顺序结构:自上而下 条件分支选择结构: if条件语句 1,一旦某一个分支确定执行以后,其他分支就不会执行.if后面的条件必须是boolean类型 2,if 后面如果不加大括号,默认相邻的下一 ...
- Java学习笔记之基础语法(数据类型)
8种基本数据类型 整型: byte[1字节] short[2字节] int[4字节] long[8字节] 1,四种整型之间的区别:申 ...
- Python 学习笔记(基础语法 restful 、 Flask 和 Requests)
input 函数 #!/usr/bin/env python3 name = input("\n\n按下 enter 键后退出.") print(name) print() 在 p ...
随机推荐
- C/C++ 通过CRC32实现反破解
我们可以通过使用CRC32算法计算出程序的CRC字节,并将其写入到PE文件的空缺位置,这样当程序再次运行时,来检测这个标志,是否与计算出来的标志一致,来决定是否运行程序,一旦程序被打补丁,其crc32 ...
- Yarp 与 Nginx性能大比拼不出所料它胜利了!
Yarp 与 Nginx 性能大比拼 测试环境: Ubuntu 22.04.3 LTS (GNU/Linux 6.5.0-14-generic x86_64) Intel(R) Xeon(R) CPU ...
- CF911G Mass Change Queries 题解
题目链接:CF 或者 洛谷 前置知识点:平衡树合并: CF文章 与维基百科 看上去这题有很多人用线段树分裂与合并去做,其实这种需要分裂和合并的,我们用文艺平衡树去维护区间信息是最容易写的. 考虑本题的 ...
- pandas教程01: pandas的安装和基本操作
pandas是Python中常用的数据处理库,主要用来处理表格数据,类似于下面这种: 好好干文化有限公司员工薪资表 姓名 年龄 性别 年薪 奖金 久九刘 35 男 182600 42000 傅儿待 ...
- 音频处理实用AI工具
最近在做音频处理相关的工作,主要有以下几个好用的工具. 1. 语音转文字--whisper 这是一款由OpenAI开发的语音转文字工具,项目地址位于:openai/whisper. 这个工具是用来生成 ...
- Java商城单体和微服务架构有什么区别
微服务架构 概述 BizSpring移动全端国际化电商平台,是建立在Spring Cloud 基础上的微服务应用,服务化是系统达到一定规模以后的必然选择,主流的互联网公司基本都在迁移到服务化架构. 我 ...
- MySQL8-[问题解决]java.sql.SQLNonTransientConnectionException: Cannot load connection class because of underlying
对应为MySQL8和 MySQL-connecter8.0.16 1.修改MySQL驱动器 原来的版本: com.mysql.jdbc.Driver 现在改为:com.mysql.cj.jdbc.Dr ...
- [JVM] JVM的类加载机制
JVM的类加载 首先我们来看下Java虚拟机的类加载过程: 如上图. 当JVM需要用到某个类的时候,虚拟机会加载它的 .class 文件.加载了相关的字节码信息之后,会常见对应的 Class 对象,这 ...
- CF1833G Ksyusha and Chinchilla
题目链接 题解 知识点:贪心,树形dp. 当 \(3 \not \mid n\) 时,显然无解. 考虑一种贪心策略,从叶子节点往上只,要以当前节点为根的子树大小能被 \(3\) 整除,就立刻切除这棵子 ...
- Centos7的KVM安装配置详解
KVM和虚拟化 虚拟化有几种类型: 完全虚拟化(Full virtualization), 虚机使用原始版本的操作系统, 直接与CPU通信, 是速度最快的虚拟化. 半虚拟化(Paravirtualiz ...