首页 > 其他分享 >volatile、extern、static、expilcit、const关键字

volatile、extern、static、expilcit、const关键字

时间:2024-06-10 20:31:17浏览次数:18  
标签:const 函数 int expilcit 静态 flag static void

一、volatile

  volatile关键字用于告诉编译器,一个变量的值可能在程序执行期间以不可预见的方式发生变化,编译器不应对该变量进行优化。即:编译器不能对这个变量进行优化,必须每次都从内存中读取它的值,而不能缓存到寄存器中。

示例: 

volatile int flag = 0;

void check_flag() {
    while (!flag) {
        // 等待flag改变
    }
    // flag改变后继续执行
}

        void check_flag():这个函数是用来检查 flag 的值,如果 flag0,函数会一直在 while 循环中等待,直到 flag 被修改为非零值。

        { // 等待flag改变 }:在这个循环体内没有任何操作,表示函数在等待 flag 发生改变。由于 flag 被声明为 volatile,每次检查 flag 的值时,都会从内存中读取最新的值,而不是使用寄存器中的缓存值。

常用于多线程编程: 一个线程可能会改变 flag 的值,而另一个线程在 check_flag 函数中等待 flag 的改变。示例如下:

假设我们有两个线程:

  • 线程1:负责执行某些操作,并在完成后将 flag 设置为1。
  • 线程2:负责调用 check_flag 函数,等待 flag 的值变为1,然后继续执行。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

volatile int flag = 0;

void* thread1_func(void* arg) {
    // 执行一些操作
    sleep(2); // 模拟操作延迟
    flag = 1; // 设置flag
    return NULL;
}

void* thread2_func(void* arg) {
    check_flag(); // 等待flag改变
    printf("Flag has been set to 1, continuing...\n");
    return NULL;
}

int main() {
    pthread_t thread1, thread2;
    
    pthread_create(&thread1, NULL, thread1_func, NULL);
    pthread_create(&thread2, NULL, thread2_func, NULL);
    
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    
    return 0;
}

在这个示例中,线程2会一直等待,直到线程1将 flag 设置为1,然后线程2继续执行并打印消息。 

        总结来说,volatile 关键字确保 flag 的变化能被及时察觉到,避免编译器的优化导致程序逻辑错误。 

 二、 extern

  extern关键字用于声明变量或函数是在另一个文件中定义的,并且可以在多个文件之间共享。它告诉编译器变量或函数的定义在其他地方。 

  • 跨文件变量:用于在多个源文件中共享全局变量。
  • 函数声明:在头文件中声明函数,以便在其他源文件中调用。

变量声明示例:

// file1.c
int shared_variable = 10;

// file2.c
extern int shared_variable;

void function() {
    // 可以访问shared_variable
    shared_variable = 20;
}

函数声明示例: 

// header.h
extern void shared_function(void);

// file1.c
#include "header.h"
void shared_function() {
    // 函数实现
}

// file2.c
#include "header.h"
void another_function() {
    shared_function(); // 调用共享函数
}

三、static 

static关键字有多种用途,具体取决于它是用在变量、函数还是类成员上。

  • 静态局部变量:在函数内声明的静态变量在函数调用之间保持其值,并且仅在第一次调用时初始化。
  • 静态全局变量:在文件范围内声明的静态变量只能在该文件中访问(即具有文件范围)。
  • 静态函数:静态函数只能在声明它的文件中访问。
  • 类的静态成员(C++):类的静态成员属于类,而不是类的任何实例。它们在所有实例间共享。

静态局部变量示例:

        每次调用 counter 函数时,count 的值都会在上一次的基础上增加 1,并打印当前的 count 值。因此,第一次调用 count1,第二次调用 count2,以此类推。 

void counter() {
    static int count = 0; // 只初始化一次
    count++;
    printf("Count: %d\n", count);
}

静态全局变量示例:

// file1.c
static int file_scope_variable = 0;

void function() {
    file_scope_variable++;
}

// file2.c
extern void function();

void another_function() {
    function(); // 不能直接访问file_scope_variable
}

静态函数示例:

// file1.c
static void static_function() {
    // 仅在file1.c中可见
}

void public_function() {
    static_function();
}

类的静态成员示例(C++): 

class MyClass {
public:
    // 类内静态成员变量声明
    static int static_member;
    static void static_method() {
        // 可以访问static_member
    }
};

// 类外定义静态成员
int MyClass::static_member = 0;

int main() {
    MyClass::static_member = 5;// 通过类名访问和修改静态成员变量
    MyClass::static_method();// 通过类名调用静态成员函数
    
    // 也可以通过对象访问静态成员变量和函数
    MyClass obj;
    obj.static_member = 10;
    obj.static_method();

    return 0;
}

四、explicit

  explicit 关键字用于构造函数声明,防止隐式类型转换。通常,单参数的构造函数可以被用于隐式类型转换,这可能会导致意外的行为。使用 explicit 关键字可以避免这种隐式转换。

示例: 

#include <iostream>

class A {
public:
    // 使用 explicit 关键字
    explicit A(int x) {
        std::cout << "Constructor called with value: " << x << std::endl;
    }
};

int main() {
    A a1 = 10; // 错误:因为构造函数是 explicit,不允许隐式转换
    A a2(20);  // 正确:显式调用构造函数
    A a3 = A(30); // 正确:显式调用构造函数
    return 0;
}

构造函数的隐式转换请看:隐式转换

五、const

  const 关键字用于声明常量,防止变量被修改。它可以用于修饰变量、成员函数、指针等。

常量变量示例:

const int value = 10;
value = 20; // 错误:value 是常量,不允许修改

常量指针示例:

int x = 10;
const int* p = &x; // p 是指向常量整数的指针,不能通过 p 修改 x 的值
*p = 20; // 错误:不允许修改指向的值
int* const p2 = &x; // p2 是常量指针,指针本身不能修改,但指向的值可以修改
int y = 20;
p2 = &y; // 错误:不允许修改指针本身
*p2 = 20; // 正确:可以修改指向的值

常量成员函数示例: 

class MyClass {
public:
    // 常量成员函数,表示该函数不会修改成员变量
    int getValue() const {
        return value;
    }
    // 非常量成员函数,可以修改成员变量
    void setValue(int val) {
        value = val;
    }
private:
    int value;
};

int main() {
    MyClass obj;
    obj.setValue(10); // 调用非常量成员函数
    std::cout << obj.getValue() << std::endl; // 调用常量成员函数
    return 0;
}

六、总结

  • volatile:告诉编译器不要优化这个变量,变量可能随时改变。
  • extern:声明变量或函数在其他文件中定义,用于跨文件访问。
  • static:用于声明局部静态变量、文件范围的静态全局变量和静态函数,以及类的静态成员(C++),控制变量和函数的作用域和生命周期。
  • explicit用于构造函数声明,防止隐式类型转换,确保类型转换的显式性。
  • const用于声明常量,防止变量、指针或对象被修改,确保代码的安全性和可维护性。

标签:const,函数,int,expilcit,静态,flag,static,void
From: https://blog.csdn.net/qq_51647149/article/details/139575701

相关文章

  • Vitis HLS 学习笔记--static RAM/ROM
    目录1.简介2.staticRAM2.1无reset的情形2.2含reset的情形3.staticROM4.总结1.简介本文仍然是讨论阵列的初始化与复位问题,区别于《VitisHLS学习笔记--global_array_RAM初始化及复位-CSDN博客》,本文讨论的对象是静态阵列,RAM和ROM。静态阵列可以映射到B......
  • Java入门基础11:面向对象高级一(static、extends继承)
    Java面向对象高级特性有以下几个:继承,多态,封装,抽象,接口,匿名内部类,静态成员,final关键字,异常处理等。我会将它分为三章详细讲,本章主要讲静态和继承staticstatic叫静态,可以修饰成员变量、成员方法。类变量(静态成员变量):有static修饰,属于类,在计算机里只有一份,会被类的全部对象......
  • 类和对象(下+)_const成员、初始化列表、友元、匿名对象
    类和对象(下+)文章目录类和对象(下+)前言一、const成员二、友元1.友元函数2.友元类三、初始化列表四、explicit关键字五、匿名对象总结前言static成员、内部类、const成员、初始化列表、友元、匿名对象一、const成员将const修饰的“成员函数”称之为const成员函数......
  • const用法详解以及auto用法详解
    const用法详解:主要用途:定义一个不可修改的常量1、修饰变量:语法:const数据类型变量名=值;示例:constintN=3;说明:const修饰的变量必须在声明时初始化,并且之后不能被修改。2、修饰指针2.1、常量指针:语法:数据类型*constp=&a;示例:int*constp=&a;说明:指针本......
  • const详解
    关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变。但是,可以通过取地址进行修改。 将const在指针前进行修饰,那么就修饰指针所指向的变量。但是指针变量可以被修改。  将const在指针后进行修饰,那么就修饰指针变量本身。但是指针指向的......
  • 【C++修行之道】类和对象(五)日期类的实现、const成员、取地址及const和取地址操作符重
    目录一、日期类的实现Date.h 1.1GetMonthDay函数(获取某年某月的天数) 问:这个函数为什么不和其他的函数一样放在Date.cpp文件中实现呢?1.2CheckDate函数(检查日期有效性)、Print函数(打印日期)1.3实现日期类的逻辑运算符重载<运算符的重载 ==运算符重载其他运算符重载......
  • 为什么Java中的main方法必须是public static void的?
    当我们创建main方法时,首先都是public、都是static,返回值都是void,方法名都是main,入参都是一个字符串数组。在以上的方法声明中,唯一可以改变的部分就是方法的参数名,我们可以吧args改成任意我们想要使用的名字。main方法时JVM执行的入口,为了方便JVM的调用,所以需要将他的访问权限......
  • 【Java】static 修饰变量
    static一种java内置关键字,静态关键字,可以修饰成员变量、成员方法。static+成员变量1.static+成员变量2.类变量图解3.类变量的访问4.类变量的内存原理5.类变量的应用1.static+成员变量成员变量按照有无static修饰,可以分为类变量:static+变量,属于类,仅存一......
  • static 在c语言中的价值
    1.概要static在c语言中的价值。static还有一个在文件内部使用有效的限制。如果在函数的外部,被static修饰的变量或者函数,是不可以在文件外部访问的,也就是说不同的文件中,被static修饰的函数或者变量是可以重名的。static的这个特性,在c++中显得有些鸡肋,但在c中的价值却很大,几......
  • static vs Singleton,静态类vs单例模式之争
    https://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern?answertab=modifieddesc#tab-top单例模式可以用接口,Singletoncanimplementinterface可以通过单例类来实现接口,但不能通过类的静态方法或者在某些语言(如C#)中的静态类来......