美文网首页C++
02-Extern、内联函数和Const

02-Extern、内联函数和Const

作者: 一亩三分甜 | 来源:发表于2021-07-16 03:23 被阅读0次

    《C++文章汇总》
    上一篇文章介绍了《01-Cin、Cout、函数重载和默认参数》,本文介绍Extern、内联函数Inline和Const。

    1.被extern "C"修饰的代码会按照C语言的方式去编译

    两种写法,一种是加载头部,另一种是用大括号包住
    I.加在头部extern "C"

    #include <iostream>
    using namespace std;
    extern "C" void func(){
        
    }
    extern "C" void func(int v1){
        
    }
    int main(int argc, const char * argv[]) {
        getchar();
        return 0;
    }
    //报错,不允许重载,C语言不支持重载
    

    II.大括号包住

    extern "C" {
        void func(){
        
        }
        void func(int v1){
        
        }
    }
    

    2.如果函数同时有声明和实现,要让函数声明被extern "C"修饰,函数实现可以不修饰,声明和实现同时修饰也不会报错

    extern "C" void func();
    extern "C" void func0(int v1);
    int main(int argc, const char * argv[]) {
        getchar();
        return 0;
    }
    extern "C" void func(){
    
    }
    extern "C" void func0(int v1){
     
    }
    

    extern "C"也可以用来包住声明头部

    extern "C" {
        void func();
        void func0(int v1);
    }
    int main(int argc, const char * argv[]) {
        getchar();
        return 0;
    }
    extern "C" void func(){
    
    }
    extern "C" void func0(int v1){
     
    }
    

    由于C、C++编译规则的不同,在C、C++混合开发时,可能会经常出现以下操作
    C++在调用C语言API时,需要使用extern "C"修饰C语言的函数声明

    #include "main.h"
    
    int sum(int v1,int v2){
        return v1 + v2;
    }
    int sub(int v1,int v2){
        return v1 - v2;
    }
    
    extern "C" {
    int sum(int v1,int v2);
    int sub(int v1,int v2);
    }
    int main(int argc, const char * argv[]) {
        
        cout << sum(10, 20) << endl;
        cout << sub(30, 20) << endl;
        
        getchar();
        return 0;
    }
    

    新建头文件如main.h存放函数的声明,在要调用的类中引用

    extern "C" {
         #include "main.h"
    }
    int main(int argc, const char * argv[]) {
        
        cout << sum(10, 20) << endl;
        cout << sub(30, 20) << endl;
        cout << divide(30, 2) << endl;
        
        getchar();
        return 0;
    }
    

    也可直接在头文件中指定,C++文件中默认定义了宏#define __plusplus在文件的第一句,在C文件中通过宏定义环境判断

    #ifdef __cplusplus
    extern "C" {
    #endif
    int sum(int v1,int v2);
    int sub(int v1,int v2);
    int divide(int v1,int v2);
    #ifdef __cplusplus
    }
    #include "main.h"
    int main(void) {
        cout << sum(10, 20) << endl;
        cout << sub(30, 20) << endl;
        cout << divide(30, 2) << endl;
        getchar();
        return 0;
    }
    

    C文件调用C文件,C文件中也可以用宏定义判断

    #include "main.h"
    extern "C" {
    #include "other.h"
    }
    int main(void) {
        
        other();
        
        cout << sum(10, 20) << endl;
        cout << sub(30, 20) << endl;
        cout << divide(30, 2) << endl;
        
        getchar();
        return 0;
    }
    //输出
    other - 30
    30
    10
    15
    

    3.防止重复引入头文件,重复引入也没用了,后面的代码也不会执行了,因为#ifndef other_h表示没有定义,才会定义往下执行,第二次头文件引入时,已经定义了宏other_h,不会再往下执行,也可以大写,前面加两个__,比如__OTHER_H,保证宏名不一样,这样多个头文件引入的时候不会相互影响

    #ifndef other_h
    #define other_h
    
    #include <stdio.h>
    void other();
    #endif /* other_h */
    
    #ifndef main_h
    #define main_h
    #include <stdio.h>
    #ifdef __cplusplus
    extern "C" {
    #endif
    int sum(int v1,int v2);
    int sub(int v1,int v2);
    int divide(int v1,int v2);
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    在新文件中能同事包含
    #include "main.h"
    #include "other.h"
    

    4.我们经常使用#ifndef、#define、#endif来防止头文件的内容被重复包含,#pragma once可以防止整个文件的内容被重复包含

    pragram once也可以防止重复包含,引入了很多次头文件保证只引入了一次

    区别

    I.ifndef、#define、#endif受C\C++标准的支持,不受编译器的任何限制
    II.有些编译器不支持#pragma once(较老编译器不支持,如GCC 3.4版本之前),兼容性不够好
    III.#ifndef、#define、#endif可以针对一个文件中的部分代码,而#pragma once只能针对整个文件

    5.内联函数

    • 使用inline修饰函数的声明或者实现,可以使其变成内联函数
    • 建议声明和实现都增加inline修饰

    特点:编译器会将函数调用直接展开为函数体代码,可以减少函数调用的开销,会增大代码体积

    • 什么时候使用内联函数?
      1.函数代码体积不大
      2.频繁调用的函数
    • 递归的调用添加Inline意义不大,编译器会识别,内联不起作用,还是存在函数调用
    • 注意
      尽量不要内联超过10行代码的函数 有些函数即使声明为inline,也不一定会被编译器内联,比如递归函数
    #include <iostream>
    using namespace std;
    //开辟栈空间
    void func(){
        cout << "void func1()" << endl;
        cout << "void func2()" << endl;
        cout << "void func3()" << endl;
    }//回收栈空间
    int sum(int v1,int v2){
        return v1+v2;
    }
    inline void func0(){
        cout << "void func1()" << endl;
        cout << "void func2()" << endl;
        cout << "void func3()" << endl;
    }
    int sum0(int v1,int v2){
        return v1+v2;
    }
    int main(int argc, const char * argv[]) {
        func0();
        cout << sum0(10, 20) << endl;
        func();
        cout << sum(10, 20) << endl;
        return 0;
    }
    //输出
    void func1()
    void func2()
    void func3()
    30
    void func1()
    void func2()
    void func3()
    30
    

    6.内联函数与宏

    内联函数和宏,都可以减少函数调用的开销
    对比宏,内联函数多了语法检测和函数特性

    • 思考以下代码的区别
    • define sum(x) (x + x)

    • inline int sum(int x) { return x + x; }
    • int a = 10; sum(a++);

    7.C++的有些表达式是可以被赋值的

    int a = 1;
    int b = 2;
    //赋值给了a
    (a = b) = 3;
    //赋值给了b
    (a < b ? a : b) = 4;

    8.Const

    ◼ const是常量的意思,被其修饰的变量不可修改 如果修饰的是类、结构体(的指针),其成员也不可以更改

    #include <iostream>
    using namespace std;
    
    struct Date {
        int year;
        int month;
        int day;
    };
    
    int main(int argc, const char * argv[]) {
        /*
        const Date d = {2011,2,5};
        Date d2 = {2013,4,8};
        d = d2;
        d.year = 2018;
         */
        Date d1 = {2011,2,5};
        Date d2 = {2013,4,8};
        const Date *p = &d1;
        p->year = 2019;
        (*p).month = 5;
        *p = d2;
        cout << d1.year << endl;
        return 0;
    }
    //会报错,通过指针也无法修改了
    

    ◼ 以下5个指针分别是什么含义?


    image
        int age = 10;
        int height = 30;
        //p1不是常量,*p1是常量
        const int *p1 = &age;
        //p2不是常量,*p2是常量
        int const *p2 = &age;
        //p3是常量,*p3不是常量
        int * const p3 = &age;
        //p4是常量,*p4也是常量
        const int * const p4 = &age;
        //p5是常量,*p5也是常量
        int const * const p5 = &age;
        
        *p4 = 20;//age = 20;
        p4 = &height;
        *p4 = 40;//height = 40;
    

    ◼ 上面的指针问题可以用以下结论来解决:
    const修饰的是其右边的内容


    image

    pStu1->age = 30也是想修改指针变量pStu1指向的内容,但指针变量*pStu1为常量,不能被修改,会报错

    相关文章

      网友评论

        本文标题:02-Extern、内联函数和Const

        本文链接:https://www.haomeiwen.com/subject/czjvpltx.html