C语言常见关键字:一文打尽

news2024/11/16 19:28:15

关键字

    • 1. 前言
    • 2. 什么是关键字
    • 3. extern-声明外部符号
    • 4. auto-自动
    • 5. typedef-类型重定义(类型重命名)
    • 6. register-寄存器
      • 6.1 存储器
      • 6.2 register关键字的作用
    • 7. static-静态
      • 7.1 static修饰局部变量
        • 7.1.1 代码对比
        • 7.1.2 原理分析
      • 7.2 static修饰全局变量
        • 7.2.1 代码对比
        • 7.2.2 原理分析
      • 7.3 static修饰函数
        • 7.3.1 代码对比
        • 7.3.2 原理分析

在这里插入图片描述

1. 前言

大家好,我是努力学习游泳的鱼。关键字,这名字一听,就很关键。而有些关键字,你可能不是很了解,更别谈使用。所以,这篇文章将带你见识常见的关键字,一起领略它们的风采吧。

2. 什么是关键字

C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,

用户自己是不能创造关键字的。

大部分关键字会在其他章节介绍,这里仅介绍一些稍微有点难度的关键字。

3. extern-声明外部符号

extern可以用来声明外部符号,如外部的全局变量和函数。
如我们在test1.c里定义了全局变量aint a = 2022;
我们想在test2.c里使用,就得先用extern声明一下extern int a;
注意:一般extern是用来声明外部的全局变量的。因为如果直接写int a;就不是声明了,而是定义,会直接创建一个变量a。只有写extern int a;才是声明变量a。如果是声明外部的函数,可以省略掉extern。如直接写int Add(int, int);和写extern int Add(int, int);效果是相同的。

4. auto-自动

C语言里的局部变量,进入局部范围时自动创建,出局部范围时自动销毁。这种自动创建,自动销毁的特性,其实是由于前面省略了关键字auto。比如,int a = 0;其实编译器会处理为auto int a = 0;一般来说,auto会被省略掉。

5. typedef-类型重定义(类型重命名)

typedef关键字用于给类型起别名,相当于起了个外号。
比如unsigned int num = 10;如果我们嫌unsigned int这个类型写起来太麻烦了,可以给它起个别名叫做uint:typedef unsigned int uint;这样上面的代码就等价于uint num = 10;

6. register-寄存器

6.1 存储器

数据的存储,需要存储器。常见的存储器有:

网盘,硬盘,内存,高级缓存,寄存器。
从左到右,速度越快,从而造价越高,从而空间越小。

早期,CPU处理的数据都来自内存。当时,CPU的处理速度和内存的读写速度是差不多的。随着技术的迭代,内存的读写速度逐渐跟不上CPU的处理速度,CPU在很大程度上被闲置了。
于是就有了这么一层设计。在内存之上设置读写速度更快的高级缓存和寄存器。CPU从寄存器中拿数据,与此同时,寄存器从高级缓存中拿数据,高级缓存从内存中拿数据。如果CPU想要的数据在寄存器中没有,那就直接从高级缓存中拿数据,如果还没有再从内存中拿。由于大部分数据都能在寄存器中命中,整体上,处理数据的速度就提升了
以上,我们能明白一点:

寄存器的读写速度是非常快的

6.2 register关键字的作用

如果我们写int num = 10;num是放在内存中的。如果我们加了个registerregister int num = 10;此时register的作用是建议num放在寄存器中。注意只是建议,实际是否放在寄存器中取决于编译器的处理。

7. static-静态

在C语言中,static有3种用法,分别修饰局部变量,全局变量和函数

1.修饰局部变量-称为静态局部变量
2.修饰全局变量-称为静态全局变量
3.修饰函数-称为静态函数

7.1 static修饰局部变量

7.1.1 代码对比

下面代码的输出结果是多少呢?

#include <stdio.h>

void test()
{
	int a = 5;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}

	return 0;
}

输出结果:10个6
为什么呢?test函数被调用了10次,每次都做了同样一件事,创建a并初始化为5a自增变成6,打印a(即6)。本质上,每次进入test函数都会创建a,出test函数时都会销毁a。这是由于局部变量的特性:进入局部范围创建,出局部范围销毁。那么,每次进入test函数创建的都是一个新的a,和之前创建的a没有任何关系。
明白这点后,再看下面这段代码,输出的结果又是多少?

#include <stdio.h>

void test()
{
	static int a = 5;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}

	return 0;
}

答案:输出6~15
分析一下:第一次调用test函数时和没有static相同,创建a并初始化,自增,打印(此时a6),但第二次调用怎么就打印7了呢?这说明,第二次调用时,a还是上次调用留下来的6,才会自增变成7!也就是说,第一次调用结束后,a并没有销毁,第二次调用时依然存在。同理,第二次调用后a也没有销毁,第三次调用时a仍是第二次调用留下来的7,然后自增变成8后打印,以此类推。

static修饰局部变量的时候,局部变量就变成了静态的局部变量,出了局部的范围,不会销毁,下一次进入函数依然存在。

7.1.2 原理分析

内存可以分为:栈区,堆区,静态区,等等。
栈区存储的是局部变量,函数参数,等等。
堆区是用来动态内存开辟的,与之相关的函数有malloc,realloc,callocfree等等。
静态区存储的是静态变量和全局变量。
静态的局部变量出了作用域依然存在,是因为它是存储在静态区的。
同样存储在静态区的全局变量,生命周期也很长。

static修饰局部变量时,实际改变的是变量的存储位置,本来一个局部变量是放在栈区的,被static修饰后放在了静态区,从而导致,出了作用域依然存在,生命周期并没有结束。
注意:放在静态区的变量出了作用域不销毁,相当于生命周期变长了,但是作用域并没有发生变化,也就是说,静态的局部变量仍然只能在它的局部范围内使用!
静态区中的数据的生命周期和程序的生命周期是一致的。程序结束,静态数据的生命周期也就到了。

7.2 static修饰全局变量

7.2.1 代码对比

我们创建两个源文件,test1.ctest2.c
test1.c里定义一个全局变量g_val

// test1.c
int g_val = 2022; // 全局变量,定义在test1.c中

test2.c内部使用这个全局变量,由于全局变量的作用域是整个工程,所以可以跨源文件使用。但是在使用前需要使用extern声明,否则会报编译错误。

// test2.c
extern int g_val;

int main()
{
	g_val = 2023;
	
	return 0;
}

如果我们在g_val的定义前面加上static会发生什么呢?

// test1.c
static int g_val = 2022; // 全局变量,定义在test1.c中

// test2.c
extern int g_val;

int main()
{
	g_val = 2023;
	
	return 0;
}

此时会报链接错误,因为g_val是定义在test1.c里的静态全局变量,不能在test2.c内部使用。看来静态的全局变量不能跨文件使用了。

7.2.2 原理分析

一个全局变量本来是具有外部链接属性的,既能在自己所在的源文件内部使用,也能在其他文件内部使用。
但是被static修饰之后外部链接属性就变成了内部链接属性,只能在自己所在的源文件内部使用,不能在其他文件内部使用了。
使用上感觉作用域变小了。

7.3 static修饰函数

7.3.1 代码对比

我们在test1.c里定义一个函数

// test1.c
int Add(int x, int y)
{
	return x + y;
}

test2.c内部使用,同理要先声明(此时可以省略extern),否则会报一个警告。

// test2.c
#include <stdio.h>

extern int Add(int, int); // extern可以省略

int main()
{
	int sum = Add(10, 20);
	printf("sum = %d\n", sum);
	
	return 0;
}

如果在函数定义前加上static会发生什么呢?

// test1.c
static int Add(int x, int y)
{
	return x + y;
}

// test2.c
#include <stdio.h>

extern int Add(int, int); // extern可以省略

int main()
{
	int sum = Add(10, 20);
	printf("sum = %d\n", sum);
	
	return 0;
}

此时会报链接错误,因为Add函数是定义在test1.c内部的静态函数,不能在test2.c内部使用。看来static修饰函数和修饰全局变量类似,静态的函数也不能跨文件调用。

7.3.2 原理分析

static修饰函数的作用:一个函数本来是具有外部链接属性的,但是被static修饰之后,外部链接属性就变成了内部链接属性,这时这个函数只能在自己所在的源文件内部使用,其他文件是无法使用的。
使用上的感觉好像是作用域变小了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/957888.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iOS import包

Frameworks Frameworks 顾名思义就是框架&#xff0c;是第三方打包完成看不到源码&#xff0c;可以直接使用的 在项目中引用方式 OC 引用某一个文件&#xff0c;Frameworks一般会提供一个h文件引用全部其他文件 #import <JLRoutes/JLRoutes.h>swift 引用一个包&#x…

如何使用Puppeteer进行金融数据抓取和预测

导语 Puppeteer是一个基于Node.js的库&#xff0c;可以用来控制Chrome或Chromium浏览器&#xff0c;实现网页操作、截图、PDF生成等功能。本文将介绍如何使用Puppeteer进行金融数据抓取和预测&#xff0c;以及如何使用亿牛云爬虫代理提高爬虫效果。 概述 金融数据抓取是指从…

RunnerGo:轻量级、全栈式、易用性和高效性的测试工具

随着软件测试的重要性日益凸显&#xff0c;市场上的测试工具也日益丰富。RunnerGo作为一款基于Go语言研发的开源测试平台&#xff0c;以其轻量级、全栈式、易用性和高效性的特点&#xff0c;在测试工具市场中逐渐脱颖而出。 RunnerGo是一款轻量级的测试工具&#xff0c;使用Go…

C# PaddleDetection yolo 印章检测

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using Sdcb.PaddleDetection; using Sdcb.PaddleInference; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq…

九、MySQL(DQL基础查询)如何查询表中信息?

1、DQL基础用法&#xff1a; 2、实例&#xff1a; &#xff08;1&#xff09;初始化表格&#xff1a; # 创建表头 create table things(id int comment 编号,number int comment 学号,name char(5) comment 姓名,address char(6) comment 地址,phone number int comment 电话…

传输层—UDP原理详解

目录 前言 1.netstat 2.pidof 3.UDP协议格式 4.UDP的特点 5.面向数据报 6.UDP的缓冲区 7.UDP使用注意事项 8.基于UDP的应用层协议 总结 前言 在之前的文章中为大家介绍了关于网络协议栈第一层就是应用层&#xff0c;包含套接字的使用&#xff0c;在应用层编码实现服务…

go学习part21(3)redis连接池

连接池 1.介绍 每次使用数据就就建立链接再关闭可以&#xff0c;但是如果有大量客户端频繁请求连接&#xff0c;大量创建连接和关闭会非常耗费资源。 所以就建立一个连接池&#xff0c;里面存放几个不关闭的连接&#xff0c;谁要用就分配给谁。 说明:通过Golang 对 Redis操…

hadoop学习:mapreduce的wordcount时候,继承mapper没有对应的mapreduce的包

踩坑描述&#xff1a;在学习 hadoop 的时候使用hadoop 下的 mapreduce&#xff0c;却发现没有 mapreduce。 第一反应就是去看看 maven 的路径对不对 settings——》搜索框搜索 maven 检查一下 Maven 路径对不对 OK 这里是对的 那么是不是依赖下载失败导致 mapreduce 没下下…

vscode和python离线安装超详细

1、下载vscode和python 1、vscode win7的用第一个版本,win10两个都可以,我测试的是第二个版本 如果不想去找的,文末可以从我这下载 2、python 如果已有python环境包,可以不用,我就是直接用的python环境包 如果不想去找的,文末可以从我这下载 3、python插件(pytho…

MATLAB中isequal函数转化为C语言

背景 有项目算法使用matlab中isequal函数进行运算&#xff0c;这里需要将转化为C语言&#xff0c;从而模拟算法运行&#xff0c;将算法移植到qt。 MATLAB中isequal简单介绍 语法 tf isequal(A,B) tf isequal(A1,A2,...,An) 说明 如果 A 和 B 等效&#xff0c;则 tf is…

《人工智能算法图解》书籍分享(包邮送书)

文章目录 人工智能介绍书籍分享抽奖包邮送书 人工智能介绍 人工智能算法是一种能够模拟人类智能行为的计算机算法。它通过分析和处理大量的数据&#xff0c;利用机器学习、深度学习和自然语言处理等技术&#xff0c;实现自主学习、推理和决策的能力。 人工智能算法的发展经历…

基于位置管理的企业员工考勤打卡系统设计 微信小程序

员工考勤打卡系统设计app是针对员工必不可少的一个部分。在公司发展的整个过程中&#xff0c;员工考勤打卡系统设计app担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类员工考勤打卡系统设计app程序也在不断改进。本课题所设计的 MVC基于HBuilder X的员工考勤…

【GO】LGTM_Grafana_Tempo(1)_架构

最近在尝试用 LGTM 来实现 Go 微服务的可观测性&#xff0c;就顺便整理一下文档。 Tempo 会分为 4 篇文章&#xff1a; Tempo 的架构官网测试实操跑通gin 框架发送 trace 数据到 tempogo-zero 微服务框架使用发送数据到 tempo 第一篇是关于&#xff0c;tempo 的架构&#xff…

图像库 PIL(一)

Python 提供了 PIL&#xff08;python image library&#xff09;图像库&#xff0c;来满足开发者处理图像的功能&#xff0c;该库提供了广泛的文件格式支持&#xff0c;包括常见的 JPEG、PNG、GIF 等&#xff0c;它提供了图像创建、图像显示、图像处理等功能。 基本概念 要学…

app易用性测试报告 软件app测试

易用性测试 app易用性测试应遵从GB/T25000.10-2016、GB/T25000.51-2016中的有关成熟性、可用性、容错性、易恢复性等方面的可靠性要求。依据应用场景需要&#xff0c;可让用户较长时间连续运行或使用APP&#xff0c;不应出现崩溃、闪退、卡死、无响应、响应迟缓等问题。 根据…

浅谈城市轨道交通视频监控与AI视频智能分析解决方案

一、背景分析 地铁作为重要的公共场所交通枢纽&#xff0c;流动性非常高、人员大量聚集&#xff0c;轨道交通需要利用视频监控系统来实现全程、全方位的安全防范&#xff0c;这也是保证地铁行车组织和安全的重要手段。调度员和车站值班员通过系统监管列车运行、客流情况、变电…

Java设计模式:四、行为型模式-04:中介者模式

文章目录 一、定义&#xff1a;中介者模式二、模拟场景&#xff1a;中介者模式三、违背方案&#xff1a;中介者模式3.1 工程结构3.2 创建数据库3.3 JDBC工具类3.4 单元测试 四、改善代码&#xff1a;中介者模式4.1 工程结构4.2 中介者工程结构图4.3 资源和配置类4.3.1 XML配置对…

说说你了解的 CDC

分析&回答 什么是 CDC CDC,Change Data Capture,变更数据获取的简称&#xff0c;使用CDC我们可以从数据库中获取已提交的更改并将这些更改发送到下游&#xff0c;供下游使用。这些变更可以包括INSERT,DELETE,UPDATE等。用户可以在以下的场景下使用CDC&#xff1a; 使用f…

thinkphp6 入门(2)--视图、渲染html页面、赋值

修改模板引擎 config/view.php // 模板引擎类型使用Think type > php, 2. 新建一个控制器 本文app的名称为test&#xff0c;在其下新建一个控制器User app/test/controller/User.php 注意&#xff1a;需要引用think\facade\View来操作视图 <?phpnamespace app\te…

Docker从认识到实践再到底层原理(二-3)|LXC容器

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…