基础语法

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++学习笔记之基础语法的更多相关文章

  1. Java学习笔记之---基础语法

    Java学习笔记之---基础语法 一. Java中的命名规范 (一)包名 由多个单词组成时,所有字母小写(例如:onetwo) (二)类名和接口 由多个单词组成时,所有单词首字母大写(例如:OneTw ...

  2. 2020寒假学习笔记14------Python基础语法学习(三)

    今天学习了Python的基础语法,其中学的内容有: 比较运算符.逻辑运算符.同一运算符.整数缓存问题.基本运算符.复合复制运算符.运算符优先级问题.字符串基本特点.字符串的编码.空字符串和len()函 ...

  3. Hive学习笔记:基础语法

    Hive基础语法 1.创建表 – 用户表 CREATE [EXTERNAL外部表] TABLE [IF NOT EXISTS 是否存在] HUserInfo ( userid int comment ...

  4. 【C语言C++编程学习笔记】基础语法,第一个简单的实例编程入门教程!

    C语言/C++编程学习:一个简单的实例 让我们来看一个简单的C语言程序.从下面的程序可以看出编写C语言程序的一些基本特征.   如果你能知道该程序将会在显示器上显示一些内容,那说明你还是知道一些的! ...

  5. PHP学习笔记01——基础语法

    <!DOCTYPE html> <html> <?php // 1.使用$加变量名来表示变量,php是弱类型语言,不要求在使用变量前声明,第一次赋值时变量才被创建 $a ...

  6. 01-Python学习笔记-基础语法

    Python标识符 -d           在解析时显示调试信息 -O           生成优化代码 ( .pyo 文件 ) -S           启动时不引入查找Python路径的位置 - ...

  7. java学习笔记之基础语法(一)

    1.java语言基础由关键字.标识符.注释.常量和变量.运算符.语句.函数和数组等组成. 2.1关键字 定义:被java语言赋予了特殊含义的单词 特点:关键字中所有的字母都是小写. 2.2用于定义数据 ...

  8. Java学习笔记之基础语法(顺序,条件,循环语句)

    顺序结构:自上而下 条件分支选择结构: if条件语句   1,一旦某一个分支确定执行以后,其他分支就不会执行.if后面的条件必须是boolean类型   2,if  后面如果不加大括号,默认相邻的下一 ...

  9. Java学习笔记之基础语法(数据类型)

    8种基本数据类型    整型:   byte[1字节]          short[2字节]        int[4字节]         long[8字节]      1,四种整型之间的区别:申 ...

  10. Python 学习笔记(基础语法 restful 、 Flask 和 Requests)

    input 函数 #!/usr/bin/env python3 name = input("\n\n按下 enter 键后退出.") print(name) print() 在 p ...

随机推荐

  1. C++ STL 标准模板库(排序/集合/适配器)算法

    C++ 标准模板库STL,是一个使用模板技术实现的通用程序库,该库由容器container,算法algorithm,迭代器iterator,容器和算法之间通过迭代器进行无缝连接,其中所包含的数据结构都 ...

  2. U390630 分考场题解

    题目链接:U390630 分考场 本题来自于2019年蓝桥杯国赛的题.在洛谷上也被标为了假题.原因是首先官方在需要输出浮点数的情况下,并没有开启spj,并且官方所给的数据当中,总有一两个数据以不知道到 ...

  3. 用GPT4聊天制作AI绘画搞笑视频,播放量近10w,附GPT4开通教程

    AI一天,人间一年 大家好,我是小卷,最近大家在视频号.抖音刷短视频时,是不是经常刷到那种用AI生成的聊天搞笑绘画视频.比如下面这个视频:南方小土豆来哈尔滨 又或者是AI眼中的各个大学 又或者是两个大 ...

  4. 初步体验通过 Semantic Kernel 与自己部署的通义千问开源大模型进行对话

    春节之前被 Semantic Kernel 所吸引,开始了解它,学习它. 在写这篇博文之前读了一些英文博文,顺便在这里分享一下: Intro to Semantic Kernel – Part One ...

  5. NC16856 [NOI1999]钉子和小球.md

    题目链接 题目 题目描述 有一个三角形木板,竖直立放,上面钉着n(n+1)/2颗钉子,还有(n+1)个格子(当n=5时如图1).每颗钉子和周围的钉子的距离都等于d,每个格子的宽度也都等于d,且除了最左 ...

  6. Swoole从入门到入土(19)——WebSocket服务器[文件传输]

    要利用WebSocket进行文件传输,我们需要讨论两种情况,分别是:发送方可以是客户端,和 发送方是服务端. 1.发送方是客户端  1)服务端接收 $server->on('message', ...

  7. Vue+SpringBoot+ElementUI实战学生管理系统-9.教师管理模块

    1.章节介绍 前一篇介绍了班级管理模块,这一篇编写教师管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 教师列表 修改教师 4.模块 ...

  8. 《系列二》-- 11、Aware是什么

    目录 正文 阅读之前要注意的东西:本文就是主打流水账式的源码阅读,主导的是一个参考,主要内容需要看官自己去源码中验证.全系列文章基于 spring 源码 5.x 版本. 写在开始前的话: 阅读spri ...

  9. pyhotn3.8 apt机器基础镜像构建

    FROM python:3.8.10-slim RUN sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/source ...

  10. QT - Day 4

    1  界面布局 实现登录窗口 利用布局方式,给窗口类化 选取Widget进行布局,水平布局,垂直布局,栅格布局 给用户名.密码.登录.退出按钮进行布局 默认窗口和控件之间有9间隙,可以调整layout ...