广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言学习之关键字的示例详解
  • 975
分享到

C语言学习之关键字的示例详解

C语言 关键字 2022-11-13 18:11:17 975人浏览 独家记忆
摘要

目录1. 前言2. 什么是关键字3. extern-声明外部符号4. auto-自动5. typedef-类型重定义(类型重命名)6. reGISter-寄存器6.1 存储器6.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并初始化为5,a自增变成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并初始化,自增,打印(此时a是6),但第二次调用怎么就打印7了呢?这说明,第二次调用时,a还是上次调用留下来的6,才会自增变成7!也就是说,第一次调用结束后,a并没有销毁,第二次调用时依然存在。同理,第二次调用后a也没有销毁,第三次调用时a仍是第二次调用留下来的7,然后自增变成8后打印,以此类推。

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

7.1.2 原理分析

内存可以分为:栈区,堆区,静态区,等等。

栈区存储的是局部变量,函数参数,等等。

堆区是用来动态内存开辟的,与之相关的函数有malloc,realloc,calloc和free等等。

静态区存储的是静态变量和全局变量。

静态的局部变量出了作用域依然存在,是因为它是存储在静态区的。

同样存储在静态区的全局变量,生命周期也很长。

static修饰局部变量时,实际改变的是变量的存储位置,本来一个局部变量是放在栈区的,被static修饰后放在了静态区,从而导致,出了作用域依然存在,生命周期并没有结束。

注意:放在静态区的变量出了作用域不销毁,相当于生命周期变长了,但是作用域并没有发生变化,也就是说,静态的局部变量仍然只能在它的局部范围内使用!
静态区中的数据的生命周期和程序的生命周期是一致的。程序结束,静态数据的生命周期也就到了。

7.2 static修饰全局变量

7.2.1 代码对比

我们创建两个源文件,test1.c和test2.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修饰之后,外部链接属性就变成了内部链接属性,这时这个函数只能在自己所在的源文件内部使用,其他文件是无法使用的。

使用上的感觉好像是作用域变小了。

到此这篇关于C语言学习之关键字的示例详解的文章就介绍到这了,更多相关C语言关键字内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言学习之关键字的示例详解

本文链接: https://www.lsjlt.com/news/169267.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言学习之关键字的示例详解
    目录1. 前言2. 什么是关键字3. extern-声明外部符号4. auto-自动5. typedef-类型重定义(类型重命名)6. register-寄存器6.1 存储器6.2 ...
    99+
    2022-11-13
    C语言 关键字
  • C语言关键字之autoregister详解
    目录一:auto作用域生命周期auto二:register总结:一:auto 在学习关键字auto之前我们需要先了解两个概念:作用域和生命周期。 作用域 作用域(scope)是程序设...
    99+
    2022-11-12
  • Go语言基础学习之map的示例详解
    目录Mapmap定义map基本使用判断某个键是否存在map的遍历使用delete()函数删除键值对按照指定顺序遍历map元素为map类型的切片值为切片类型的mapMap实现原理什么是...
    99+
    2023-05-14
    Golang map原理 Golang map实现 Golang map
  • java学习之路——final关键字详解
    一、概述学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承API中提供的类,改写其内容呢?显然这是不合适的。为了避免这种随意改写的情况,Java提供了final用于修饰不可改变内容。final...
    99+
    2021-08-02
    java入门 java final 关键字
  • 详解C语言中的Static关键字
    一、static关键字的基本含义 首先,static关键字的意思是静态的,用于修饰局部变量,全局变量和函数,修改其数据储存类型 1.局部变量:在任意一个函数内部定义的变量(不加sta...
    99+
    2022-11-13
  • C语言volatile关键字的作用与示例
    目录写在前面volatile和内联汇编的volatile的选择写在前面 版本信息:Linux操作系统,x86架构,Linux操作系统下GCC9.3.1版本。GCC 9.3.0手册。 ...
    99+
    2023-05-15
    C语言volatile关键字 C语言volatile
  • Go语言学习教程之反射的示例详解
    目录介绍反射的规律1. 从接口值到反射对象的反射2. 从反射对象到接口值的反射3. 要修改反射对象,该值一定是可设置的介绍 reflect包实现运行时反射,允许一个程序操作任何类型...
    99+
    2022-11-11
  • Go语言学习教程之指针的示例详解
    目录前言练习1练习2练习3前言 关于指针的主要几点: 指针类型:一个指针类型*T表示指向给定类型的变量的所有指针的集合,该给定类型T称为基本类型。未初始化的指针的值是nil。变量:一...
    99+
    2022-11-11
  • c语言static关键字用法详解
    目录1.static修饰全局变量2.static修饰函数3.static修饰局部变量总结:1.static修饰全局变量 我们创建两个源文件,一个test.c,一个main.c 现在...
    99+
    2022-11-12
  • C 语言基础之C语言的常见关键字
    目录​1、auto 2、register 3、signed和unsigned 4、typedef 5、extern 6、拓展首先我们简单的和这些关键字见见面(被高亮的关键...
    99+
    2022-11-12
  • Go语言学习教程之结构体的示例详解
    目录前言可导出的标识符嵌入字段提升标签结构体与JSON相互转换结构体转JSONJSON转结构体练习代码步骤前言 结构体是一个序列,包含一些被命名的元素,这些被命名的元素称为字段(fi...
    99+
    2022-11-11
  • 详解C语言学习记录之指针
    目录1指针是什么2指针和指针类型3野指针(1)三种情况(2)如何规避野指针4指针运算5指针和数组6字符指针7数组指针8指针数组9其他总结1指针是什么 指针是汇编语言中的一个对象,利用...
    99+
    2022-11-12
  • C语言学习之链表的实现详解
    目录一、链表的概念二、链表的结构三、顺序表和链表的区别和联系四、链表的实现一、链表的概念 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次...
    99+
    2022-11-13
    C语言 链表实现 C语言 链表
  • C语言学习之指针的使用详解
    目录一、指针概念1.指针变量2.指针类型3.二级指针二、野指针1.野指针成因2.规避野指针三、指针运算1.指针±整数2.指针-指针3.指针关系运算四、指针数组1.指针和...
    99+
    2022-11-13
    C语言指针使用 C语言指针
  • C语言入门篇--关键字static详解
    目录1.修饰局部变量1.1作用1.2举例(1)不加static(2)加static(3)静态局部变量的初始化只会进行一次2.修饰全局变量2.1作用2.2举例(1)不加static(2...
    99+
    2022-11-12
  • Go语言学习教程之goroutine和通道的示例详解
    目录goroutine通道Range 和 CloseSelect官方留的两道练习题等价的二叉树网络爬虫源码地址goroutine goroutine是由Go运行时管理的轻量级线程。 ...
    99+
    2022-11-11
  • C语言学习之标识符的使用详解
    目录命名规则命名规范示例代码总结C语言标识符是用于表示变量、函数、常量、类型等程序元素的名称。在 C语言中,标识符的命名规则和命名规范非常重要,它们直接影响到代码的可读性、可维护性和...
    99+
    2023-05-20
    C语言标识符用法 C语言标识符使用 C语言标识符
  • C语言算法学习之双向链表详解
    目录一、练习题目二、算法思路1、设计浏览器历史记录2、扁平化多级双向链表3、展平多级双向链表4、二叉搜索树与双向链表一、练习题目 题目链接难度1472. 设计浏览器历史记录★★★☆☆...
    99+
    2022-11-13
  • C语言中volatile关键字的详细介绍
    这篇文章主要讲解了“C语言中volatile关键字的详细介绍”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言中volatile关键字的详细介绍”吧!1. 什么是volatile关键字?v...
    99+
    2023-06-20
  • C语言详解关键字sizeof与unsigned及signed的用法
    目录最冤枉的关键字sizeof理解被误解为函数sizeof(int)*p 表示什么意思signed与unsigned 关键字有符号整数vs无符号整数整形在内存的存储原码反码补码存储的...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作