volatile、extern、static关键字

2024-06-10 17:04

本文主要是介绍volatile、extern、static关键字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、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; // 设置flagreturn 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_variableshared_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;
}

四、总结 

  • volatile:告诉编译器不要优化这个变量,变量可能随时改变。
  • extern:声明变量或函数在其他文件中定义,用于跨文件访问。
  • static:用于声明局部静态变量、文件范围的静态全局变量和静态函数,以及类的静态成员(C++),控制变量和函数的作用域和生命周期。

这篇关于volatile、extern、static关键字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1048747

相关文章

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

Oracle Start With关键字

Oracle Start With关键字 前言 旨在记录一些Oracle使用中遇到的各种各样的问题. 同时希望能帮到和我遇到同样问题的人. Start With (树查询) 问题描述: 在数据库中, 有一种比较常见得 设计模式, 层级结构 设计模式, 具体到 Oracle table中, 字段特点如下: ID, DSC, PID; 三个字段, 分别表示 当前标识的 ID(主键), DSC 当

关键字synchronized、volatile的比较

关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字的执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。多线程访问volatile不会发生阻塞,而synchronize

JavaScript 根据关键字匹配数组项

要在JavaScript数组中根据关键字匹配项,可以使用filter方法结合一个测试函数。以下是一个示例代码,定义了一个函数findByKeyword,该函数接受一个数组和一个关键字,然后返回一个新数组,其中包含与关键字匹配的所有项。 function findByKeyword(array, keyword) {return array.filter(item => {// 假设要匹配的是对象

MySQL 的关键字

MySQL 中的关键字是数据库中具有特殊含义的保留字,它们用于定义数据库结构、操作数据库数据和控制数据库行为。关键字在 MySQL 查询中扮演着至关重要的角色,因为它们是 SQL 语句的核心组成部分。 1. 数据定义语言 (DDL) 关键字 数据定义语言 (DDL) 关键字用于定义、修改和删除数据库结构,如数据库、表和索引等。这些关键字通常用于创建、删除表结构以及修改表的列等操作。 1.1

C++中的mutable关键字详解

目录 1.概述 2.使用场景 3.示例 4.mutable修饰Lambda表达式 5.注意事项 1.概述         在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。         我们知道,被const关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以

[Python]生成器和yield关键字

生成器和yield关键字 1.生成器介绍: 概述: ​ 它指的是 generator, 类似于以前学过的: 列表推导式, 集合推导式, 字典推导式… 作用: ​ 降低资源消耗, 快速(批量)生成数据. 实现方式: ​ 1.推导式写法. my_generator = (i for i in range(5)) ​ 2.yield写法. def get_generator():for i

java基础总结11-面向对象7(super关键字)

在JAVA类中使用super来引用父类的成分,用this来引用当前对象,如果一个类从另外一个类继承,我们new这个子类的实例对象的时候,这个子类对象里面会有一个父类对象。怎么去引用里面的父类对象呢?使用super来引用,this指的是当前对象的引用,super是当前对象里面的父对象的引用。 1 super关键字测试 package cn.galc.test;/*** 父类* @autho

java基础总结08-面向对象4(static关键字)

原来一个类里面的成员变量,每new一个对象,这个对象就有一份自己的成员变量,因为这些成员变量都不是静态成员变量。对于static成员变量来说,这个成员变量只有一份,而且这一份是这个类所有的对象共享。 静态成员变量与非静态成员变量的区别 以下面的例子为例说明 package cn.galc.test;public class Cat {/*** 静态成员变量*/private static

java基础总结07-面向对象3(this关键字)

this是一个引用,它指向自身的这个对象。 看内存分析图 假设我们在堆内存new了一个对象,在这个对象里面你想象着他有一个引用this,this指向这个对象自己,所以这就是this,这个new出来的对象名字是什么,我们不知道,不知道也没关系,因为这并不影响这个对象在内存里面的存在,这个对象只要在内存中存在,他就一定有一个引用this。 看下面的例子分析: package cn.ga