杨泽彬的神秘商店

博客园 首页 新随笔 联系 订阅 管理

关键字专题
先从一些较难理解的关键字开始

1.constexpr

参考网址: 概念描述还可以,举例有错[]:https://zhuanlan.zhihu.com/p/93641410
作为常量,计算过程可以放在编译器而不是运行期。
const和constexpr区别:

  • const没有分出编译期常量和运行时常量
  • constexpr 修饰指针时只对指针有效,与指针指向对象无关

2.

3.代用运算符

4.运算符优先级

  • x++ + ++y + y; //后续的y是会收到前面的++y运算的影响的

5.存储类说明符

  • auto
  • register:自动存储期
  • static:静态或线程存储期和内部连接
  • extern:静态或线程存储期和外部连接
  • thread_local:线程存储期
  • mutable:不影响存储期或连接

6.const_cast

强制类型转换运算符
参考网址:[]:https://www.runoob.com/cplusplus/cpp-casting-operators.html
const_cast 运算符用于修改类型的 const / volatile 属性。除了 const 或 volatile 属性之外,目标类型必须与源类型相同。
修改一些指针/引用的权限

7.volatile

volatile ——定义类型为易变。
由于volatile 易变,因此不使用寄存器中的备份而使用其本身。
遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。

8.什么情形要用到volatile

  • 并行设备的硬件寄存器
  • 多线程共享的变量
  • 中断访问的非自动变量

9.一个变量可以既是const 又是 volatile吗

可以,一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。

10.volatile操作是原子操作吗?

10.用变量a写出以下变量的定义

  • 一个正整数 `` int a ;
  • 一个指向整型数的指针 ``int *a;
  • 一个指向整型指针的指针 ``int **a;
  • 一个有10个整型数的数组 ``int a[10]; array<int,10> a;
  • 一个有10个整型指针的数组 ``int *a[10];
  • 一个指向有10整数的数组的指针 ``int (*a[10];
  • 一个指向返回整型数的函数的指针 `` int (*a)(int);
  • 一个有10个指针的数组,该指针指向一个函数,这个函数返回整型数和有一个整型参数`` int (*a[10])(int)
  • 一个常量的指针 ``int const * a; const int* a;
  • 一个指针常量``int * const a ;
  • 一个常量的指针常量``int const* const a; const int* const a;

上次遇到这段还是有点不熟悉(09-03)

【入门视角】:[]:https://www.cnblogs.com/gis-lhx/p/12483203.html

其实还是得先从结合性优先级进行判断。
比如说区分指针函数和函数指针
他们本质区别是 指针变量 还是是 函数
通过加了()使得结合优先级发生变化
函数指针:int (*fun)(int x,int y); ()将与fun先结合起来 ,fun是一个指针
指针函数:int *fun(char *s1,char *s2);//将s2指向的字符串复制到s1中 这里的fun没有和
结合起来 所以是函数

再比如说指针数组与数组指针
指针数组int *p[n]; [ ]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。
数组指针:int (*p)[n];()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n。

11. Lambda表达式

12.GCC相关的关键字

memory 破坏描述符 属于是内嵌汇编
(1)不要将该段内嵌汇编指令与前面的指令重新排序;也就是在执行内嵌汇编代码之前,它前面的指令都执行完毕。
(2)不要将变量缓存到寄存器,因为这段代码可能会用到内存变量,而这些内存变量会以不可预知的方式发生改变,因此 GCC 插入必要的代码先将缓存到寄存器的变量值写回内存,如果后面又访问这些变量,需要重新访问内存。
c语言如何进行内嵌汇编?
GCC 如何编译内嵌汇编代码:
[1] 输入变量与占位符

根据限定符和破坏描述部分,为输入和输出部分的变量分配合适的寄存器,如果限定符指定为立即数(“i”),或内存变量(“m”),则不需要该步骤,如果限定符没有具体指定输入操作数的类型(如“g”),GCC 会视需要决定是否将该操作数输入到某个寄存器。这样每个占位符都与某个寄存器、内存变量或立即数形成了一一对应的关系。对分配了寄存器的输入变量需要增加代码将它的值读入寄存器。另外还要根据破坏描述符的部分增加额外代码。

[2] 指令模板部分

然后根据这种一一对应的关系,用这些寄存器、内存变量或立即数来取代汇编代码中的占位符。

[3] 变量输出
按照输出限定符的指定将寄存器的内容输出到某个内存变量中,如果输出操作数的限定符指定为内存变量(“m”),则该步骤被省略。

13.inline关键字

为什么引入inline关键字:因为有些小函数如果被频繁调用的话,会大量消耗栈空间。

14.inline是强制命令吗?
inline只是对编译器的一种建议,而不是强制命令。最终决定实不实现的是编译器本身。编译器不会对太复杂的代码进行编译,尤其是一些含有复杂判断条件的。

15.inline的本质是什么?
inline的本质是将对函数的每一个调用都直接用代码进行替换。这样可以减小栈空间的使用。但是也存在别的问题,如果代码调用次数过多,会导致代码体积太大。
其次还可能造成额外的换页行为,然后造成更多的缓存不命中,最后反而运行时间增加。

16.inline 和宏函数的区别是什么?

  • 执行的时间不同:inline是在编译阶段完成的,而宏函数是在预编译阶段完成的
  • 语法检查:宏函数只是简单的文本替换,没有语法检查,有些优先级必须通过括号来强制执行,但是inline内联函数其本身就是一个正常的函数(自然要检查语法)
  • inline 易于调试 , 而宏函数不易于调试。

14.static关键字

这个关键字也算是见得多了。
无非是从作用域和生命周期去谈

重点针对

posted on 2022-08-09 11:30  快乐过了阈值  阅读(29)  评论(0)    收藏  举报