这是因为空指针没有与之关联的数据类型。 编译器无法知道void指针指向的数据类型。 因此,要获取由void指针指向的数据,需要使用在void指针位置内保存的正确类型的数据进行类型转换。...对于空指针的解引用,你如不信,就来看看栗子: 1.png 看到了吧,直接解引用编译不过,因为编译器蒙了。...举个栗子: /*模块A中有这样一个结构体需要非易失存储*/ typedef struct _t_paras{ int language;/*语言种类*/ char SN[20]; /*产品序列号...*/ }T_PARAS; T_PARAS sysParas; /*模块B中有这样一个结构体需要非易失存储*/ typedef struct _t_pid{ float kp; float...4.png 总结一下 这篇文章引入了一些编程思想,对于单片机/嵌入式进阶编程比较有用: 利用void *指针,将业务数据与底层存储实现了抽象解耦 利用分层抽象实现了代码具有良好的可移植性 利用函数指针实现了
回答: 的易失性的关键字是类型限定符防止从编译器optimization.According至C标准的对象,具有挥发性限定类型可以以实施方式未知进行修改或具有其他未知侧effects.You也可以说,一个对象可以随时更改...我们可以有一个易失性指针吗? 回答: 是的,我们可以用C语言创建一个易失性指针。 int * volatile piData; // piData是一个指向整数的易失性指针。...回答: const关键字是编译器强制执行的,并且表示程序无法更改对象的值,这意味着它使对象成为不可修改的类型。...在另一方面,volatile阻止任何编译器优化,并且表示对象的值可以通过程序无法控制的内容进行更改,因此编译器不会对该对象做出任何假设。...是一个指向易失性无符号整数的常量指针,使用* pcPortReg我们可以访问内存映射寄存器。
具有ARM64内部函数的方法的AOT编译 在典型情况下,应用程序在运行时使用JIT编译为机器代码。...ARM64中的内存屏障 通过一些基准测试,我们注意到 volatile 类的关键方法的热循环中易失性变量的访问。访问ARM64的易失性变量非常昂贵,因为它们引入了内存屏障指令。...ARM内存模型 ARM体系结构具有弱有序的内存模型。处理器可以重新排序内存访问指令以提高性能。它可以重新排列指令,以减少处理器访问内存所需的时间。...ARM64具有指令集体系结构(ISA),具有固定长度的编码,每条指令的长度恰好为32位。因此,移动指令mov仅具有空间来编码最多16位无符号常量。...当用几个基准检查为.NET库生成的ARM64代码时,我们意识到有几种指令模式可以用更好,性能更高的指令代替。在编译器文献中,“窥孔优化”是进行此类优化的阶段。RyuJIT当前没有窥视孔优化阶段。
常变量初始化之后,不允许再被赋值; 正如我在这里所说,其实加了关键字const只是提示编译器这个变量是常量,如果我们在接下来的操作中试图更改它,编译器会报错,而并不是真正的常量,事实上某些情形下通过指针也是可以更改的...(三)、结构体对齐,初始化方式 什么是内存对齐 编译器为每个“数据单元”按排在某个合适的位置上。...如果调整的两个成员具有相同数据类型,编译时不会有任何警告,而程序的逻辑上可能相距十万八千里了。...C编译器编译,则__cplusplus 没有定义,extern “C" 被略过,如果头文件被C++代码包含并被C++编 译器编译,存在__cplusplus 定义故extern "c" 提示编译器不要对...不同C++编译器的name mangling 方案是不同的,这是造成不同编译器之间存在二进制连接兼容性的主要原因之一。
区别: 1)const是有数据类型的常量,而宏常量没有,编译器可以对前者进行静态类型安全检查,对后者仅是字符替换,没有类型安全检查,而且在字符替换时可能会产生意料不到的错误(边际效应)。...2)有些编译器可以对const常量进行调试, 不能对宏调试。 4. 既然C++中有更好的const为什么还要使用宏? const无法代替宏作为卫哨来防止文件的重复包含。 5....引用是对象的别名, 操作引用就是操作这个对象, 必须在创建的同时有效得初始化(引用一个有效的对象, 不可为NULL), 初始化完毕就再也不可改变, 引用具有指针的效率, 又具有变量使用的方便性和直观性,...在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。...假设某个函数的原型为: void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
const修饰的是常变量,是可寻址的,且具有外部连接性。...但是如果在定义const变量时使用extern,那么说明该const变量具有外部连接性,促使C++编译器为const变量分配存储空间,看来extern与const结合时的用法很是耐人寻味啊。...此外,还需要注意的是为什么使用const定义变量时,C++编译器并不为const变量创建存储空间,相反把这个定义保存在的符号表里。那是因为编译时会进行常量折叠。...常量折叠是其中一种被很多现代编译器使用的编译器优化技术,在编译时简化常量表达式的一个过程。简单来说就是将常量表达式计算求值,并用求得的值来替换表达式,放入常量表,可以算作一种编译优化。...如果使用extern const来前置申明一个不具有外部连接性的const变量,是会报错的,因为使用extern申明变量的前提条件是变量具有外部连接性。
C++11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一 个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。.... auto不能推导的场景 auto不能作为函数的参数 因为编译器无法对a的实际类型进行推导 auto不能直接用来声明数组 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法...这意味着你可以在函数定义时使用auto关键字指定返回类型,编译器会根据返回语句推导出具体的类型。这样做可以增加代码的可读性和灵活性,特别是在模板编程和使用lambda表达式时。...auto类型的常量N,然后返回乘积。...在实例化时,N的类型会根据提供的常量自动推导。 结构化绑定: C++17还引入了结构化绑定,这允许使用auto来解构数组、结构体和tuple,从而更容易地访问复合数据类型的元素。
inline 内联函数的特征 相当于把内联函数里面的内容写在调用内联函数处; 相当于不用执行进入函数的步骤,直接执行函数体; 相当于宏,却比宏多了类型检查,真正具有函数特性; 编译器一般不内联包含循环、...inline函数的改变需要重新编译,不像 non-inline 可以直接链接。是否内联,程序员不可控。内联函数只是对编译器的建议,是否对函数内联,决定权在于编译器。...所以使用 volatile 告诉编译器不应对这样的对象进行优化。...C 语言方式编译和链接的 extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题...C++ 中 struct 和 class 总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。 区别 最本质的一个区别就是默认的访问控制。
传统C++中枚举常量被暴漏在同一层作用域中,如果同一作用域下有两个不同的枚举类型,但含有同名的枚举常量也是会报编译错误的,比如: enum Fruits{Apple,Tomato,Orange}; enum...(2)由于枚举类型被设计为常量数值的“别名”,所以枚举常量总是可以被隐式转换为整型,且用户无法为枚举常量定义类型。 (3)枚举常量占用存储空间以及符号性不确定。...C++标准规定C++枚举所基于的“基础类型”是由编译器来具体实现,这会导致枚举类型成员的基本类型存在不确定性问题,尤其是符号性问题,即。...可见不同编译器对枚举常量的整型类型的宽度和符号有着不同的实现。GNU C++会根据枚举数值的类型使用不同宽度和符号的整型,VC++则始终以有符号int来表示枚举常量。...进而使用枚举类型的枚举成员时,必须指明所属范围,比如Enum::VAL1,而单独的VAL1则不再具有意义; (2)转换限制,强类型枚举成员的值不可以与整型发生隐式相互转换。
一些细节点 使用条件编译可以提早优化代码,产生最适合系统、编译环境的代码 “deprecated”属性只会导致编译警告,函数和类仍然可 属性标签是由编译器负责解释的,自定义标签编译器无法识别...const 常量也是变量,可以修改,但修改通常会被优化掉,无法直接体现 const 成员函数可以修改 mutable 成员变量,不是完全不可以修改变量 mutable 与 volatile...前者是指向常量的指针,后者指向的是变量,但指针是常量 shared_ptr 的行为最接近原始指针,但不能滥用 shared_ptr 有少量的成本,而且有无法克服的循环引用风险,需要搭配 weak_ptr...编译器看到 const 常量会做一些优化,比如把这个变量直接换成对应的值 只读指针对象,调用它的方法,只能调用 const 的 const_cast,去常量化,变成普通变量 volatile 表示变量会随时会被修改...,禁止编译器优化,应该少用 mutable volatile 可以用来修饰任何变量,而 mutable 却只能修饰类里面的成员变量,表示变量即使是在 const 对象里,也是可以修改的 mutable
修饰的全局常量 和 字符串常量 易混点 区分静态变量(static)与const修饰的局部变量 PS:全局变量和静态变量 1.从作用域看: (1)全局变量具有全局作用域。...system("pause"); return 0; } 易错点 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放,函数运行结束后函数内的局部变量被释放,将无法使用传回的函数体内的局部变量的地址...取决于编译器。 system("pause"); return 0; } 引用的本质 分析 本质:引用的本质在c++内部实现是一个指针常量(指针指向不可改)....引入: 类描述上像是包含成员函数以及public和private可见标签的结构声明,实际上C++对结构进行了扩展,使之具有与类相同的特性,他们只有唯一的区别是默认的访问权限不同。...#ifndef方式受C/C++语言标准的支持,不受编译器的任何限制;而#pragma once方式有些编译器不支持(较老编译器不支持,如GCC 3.4版本之前不支持#pragmaonce),兼容性不够好
,程序员无须考虑内存碎片的问题 应用场景 Java在桌面程序上不如C++实用,C++可以直接编译成exe文件,指针是c++的优势,可以直接对内存的操作,但同时具有危险性 。...static成员函数:不具有this指针,无法访问类对象的非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile;可以被非static成员函数任意访问 const...绝对类型安全的编程语言暂时还没有。 (1)C的类型安全 C只在局部上下文中表现出类型安全,比如试图从一种结构体的指针转换成另一种结构体的指针时,编译器将会报告错误,除非使用显式类型转换。...而内联函数可以进行参数类型检查(编译时),且具有返回值。 内联函数本身是函数,强调函数特性,具有重载等功能。 内联函数可以作为某个类的成员函数,这样可以使用类的保护成员和私有成员,进而提升效率。...上述观点看似正确,其实不然,如果虚函数在编译器就能够决定将要调用哪个函数时,就能够内联,那么什么情况下编译器可以确定要调用哪个函数呢,答案是当用对象调用虚函数(此时不具有多态性)时,就内联展开 综上,当是指向派生类的指针
,程序员无须考虑内存碎片的问题 应用场景 Java在桌面程序上不如C++实用,C++可以直接编译成exe文件,指针是c++的优势,可以直接对内存的操作,但同时具有危险性 。...static成员函数:不具有this指针,无法访问类对象的非static成员变量和非static成员函数;不能被声明为const、虚函数和volatile;可以被非static成员函数任意访问 const...(用该关键字声明的变量可以在const成员函数中被修改)数据的值 25、C++的顶层const和底层const 概念区分 顶层const:指的是const修饰的变量本身是一个常量,无法修改,指的是指针,...而内联函数可以进行参数类型检查(编译时),且具有返回值。 内联函数本身是函数,强调函数特性,具有重载等功能。 内联函数可以作为某个类的成员函数,这样可以使用类的保护成员和私有成员,进而提升效率。...上述观点看似正确,其实不然,如果虚函数在编译器就能够决定将要调用哪个函数时,就能够内联,那么什么情况下编译器可以确定要调用哪个函数呢,答案是当用对象调用虚函数(此时不具有多态性)时,就内联展开 综上,当是指向派生类的指针
可能存在的疑问:类体内的成员函数被编译器内联处理,但并不是所有的成员函数都会被内联处理,比如包含递归的成员函数。...如果编译器发现被定义在类体内的成员函数无法被内联处理,也不会出现重定义的错误,因为C++中存在5种作用域的级别,分别是文件域(全局作用域)、命名空间域、类域、函数作用域和代码块作用域(局部域)。...其实很简单,类体内定义的成员函数就是inline函数,即使不被内联处理,inline函数的特性就是不具有外部连接性。所以并不会与其他源文件中的同名类域中的成员函数发生冲突,也就不会造成重定义的错误。...6.小结 可以将内联理解为C++中对于函数专有的宏,对于C的函数宏的一种改进。对于常量宏,C++提供const替代;而对于函数宏,C++提供的方案则是inline。...C++ 通过内联机制,既具备宏代码的效率,又增加了安全性,还可以自由操作类的数据成员,算是一个比较完美的解决方案。
使用literal pool (文字池)的原因 当想要在一条指令中使用一个 4字节长度的常量数据(这个数据可以是内存地址,也可以是数字常量)的时候,由于ARM指令集是定长的(ARM指令4字节或Thumb...指令2字节),所以就无法把这个4字节的常量数据编码在一条编译后的指令中。...此时,ARM编译器(编译C源程序)/汇编器(编译汇编程序) 就会在代码节中分配一块内存,并把这个4字节的数据常量保存于此,之后,再使用一条指令把这个4 字节的数字常量加载到寄存器中参与运算。...在C源代码中,文字池的分配是由编译器在编译时自行安排的,在进行汇编程序设计时,开发者可以自己进行文字池的分配,如果开发者没有进行文字池的安排,那么汇编器就会代劳。 「bss段占用4个字节」 ?...所以对于需要大量访问结构体成员的功能函数,所有访问结构体成员的操作只需要加载一次基地址即可。 使用结构体就可以大大的节省指令周期,而节省指令周期对于提高cpu的运行效率自然不言而喻。
inline 内联函数 特征 相当于把内联函数里面的内容写在调用内联函数处; 相当于不用执行进入函数的步骤,直接执行函数体; 相当于宏,却比宏多了类型检查,真正具有函数特性; 编译器一般不内联包含循环...内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。...inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。...限定的函数或变量是 extern 类型的 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的 extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代码当作...原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。
inline 内联函数 特征 相当于把内联函数里面的内容写在调用内联函数处; 相当于不用执行进入函数的步骤,直接执行函数体; 相当于宏,却比宏多了类型检查,真正具有函数特性; 编译器一般不内联包含循环、...内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。...inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。...限定的函数或变量是 extern 类型的 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的 extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代码当作...原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。
C++中const有什么作用?至少说明3种 const用于定义常量:const定义的常量编译器可以对其进行数据静态类型安全检查。...const修饰类的成员函数(函数定义体):任何不需要修改数据成员的函数都应该使用const修饰,这样即使不小心修改了数据成员或调用了非const成员函数,编译器也会报错。...如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。...这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。...当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,请解释一下编译器为什么没有让它为零。 为1。
字符串常量易混点区分静态变量(static)与const修饰的局部变量程序运行后栈区分析栈区: 由编译器自动分配释放, 存放函数的参数值,局部变量等示例int * func(){ int a =...; system("pause"); return 0;}易错点不要返回局部变量的地址,栈区开辟的数据由编译器自动释放,函数运行结束后函数内的局部变量被释放,将无法使用传回的函数体内的局部变量的地址...如果假设成立,那么*func()的调用将不受次数限制,因为func()每次传回的都是最新的地址,而*p只能调用一次,因为*p经过了局部变量的存储,编译器保留了一次地址后将地址释放之后p地址将失效,无法继续访问...每个区存储的内容如下:1、栈区:存放函数的参数值、局部变量等,由编译器自动分配和释放,通常在函数执行完后就释放了,其操作方式类似于数据结构中的栈。...2、堆区:就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。“内存泄漏”通常说的就是堆区。
也就是说,编译器可能并不支持递归常量表达式函数。不过也不用过于担心,主流的C++编译器都是支持的,比如GCC和VC++。...5.3 constexpr与const的区别 const可以修饰函数参数、函数返回值、函数本身、类等,在不同的使用场景下,const具有不同的意义,不过大多数情况下,const描述的是“运行时常量性”,...constexpr可以修饰函数参数、函数返回值、变量、类的构造函数、函数模板等,是一种比const更加严格的约束,它修饰的表达式除了具有“运行时常量性”,也具有“编译时常量性”,即constexpr修饰的表达式的值在编译期间可知...在实际开发中,建议大家重写继承而来的虚函数时,加上关键字virtual表明当前函数是虚函数,C++编译器的“放纵”降低了代码可读性。...,用编译器来强制保证一些契约,改善编译信息的可读性,尤其是用于模板的时候; (3)编译器在遇到一个static_assert语句时,通常立刻将其第一个参数作为常量表达式进行演算。
领取专属 10元无门槛券
手把手带您无忧上云