C语言关键字(三)

之前的两篇文章

嵌入式Linux:c语言深度解剖(数据类型关键字)​zhuanlan.zhihu.com

嵌入式Linux:c语言深度解剖(入门篇)​zhuanlan.zhihu.com

这篇文件继续讲解C语言关键字

想问大家一个问题,什么是声明什么是定义?

举个例子:

A)int i;

B)extern int i;(关于 extern,后面解释)

哪个是定义?哪个是声明?或者都是定义或者都是声明?

什么是定义:所谓的定义就是(编译器)创建一个对象,为这个对象分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名或对象名。但注意,这个名字一旦和这块内存匹配起来,它们就同生共死,终生不离不弃。并且这块内存的位置也不能被改变。一个变量或对象在一定的区域内(比如函数内,全局等)只能被定义一次,如果定义多次,编译器会提示你重复定义同一个变量或对象。

什么是声明:有两重含义,如下:

第一重含义:告诉编译器,这个名字已经匹配到一块内存上了,(就比如你拿出结婚证告诉别人,我已经和别的内存块结婚了,请不要再勾搭我了)。

第二重含义:告诉编译器,我这个名字我先预定了,别的地方再也不能用它来作为变量名或对象名。(这个就有点耍赖,你拿着一个假的结婚证告诉别人,我已经结婚了,但是实际上,你还没有妹子,还没有分配内存空间)。

好,这样一解释,我们可以很清楚的判断:A)是定义;B)是声明。

那他们的区别也很清晰了。记住,定义声明最重要的区别:定义创建了对象并为这个对象一块内存,而声明的时候是没有分配内存空间的。

 

1,不需要记住的关键字----auto

auto:他太普通了,你就当它不存在吧。编译器在默认的缺省情况下,所有变量
都是 auto 的。

2,最快的关键字---- register

register:这个关键字请求编译器尽可能的将变量存在 CPU 内部寄存器中而不是通过内
存寻址访问以提高效率。注意是尽可能,不是绝对。你想想,一个 CPU 的寄存器也就那么
几个或几十个,你要是定义了很多很多 register 变量,它累死也可能不能全部把这些变量放
入寄存器吧,轮也可能轮不到你。

2.1,皇帝(CPU)身边的小太监----寄存器

把cpu类比成为一个皇帝,那register就是皇帝身边的小太监了,不知道大家见过太监没有,我们看各种宫斗剧的时候,太监是唯命是从,只要皇帝叫做什么,太监马上就去做,速度之快令人瞠目结舌,也就是因为速度快,所以皇帝才配有太监,而且不止有一个太监,太监就像一个文件中转站,把下面人的折子拿给皇帝批阅。

所以太监的特点是

1、响应速度快

2、数量少,只给皇帝工作

3、价格贵



2.2,使用 register 修饰符的注意点

虽然寄存器的速度非常快,但是使用 register 修饰符也有些限制的:register 变量必须是能被 CPU 寄存器所接受的类型。意味着 register 变量必须是一个单个的值,并且其长度应小于或等于整型的长度。 而且 register 变量可能不存放在内存中,所以不能用取址运算符“&”来获取 register 变量的地址。

3、确定位置的关键字----static

3.1、static 修饰变量

修饰静态全局变量:作用域仅限制于被定义的文件中,其他文件即使用extern声明也没有办法使用,作用域从定义之处开始,到文件结尾处,在定义之前的代码不能使用。本文件可以在之前加extern ,不过这样还不如直接在顶端定义。

 

静态全局变量:在函数体里面定义的,就只能在函数里面使用了,由于static定义的变量存在静态区,改函数执行结束,变量的值还是存在,不会销毁,下次该函数调用时,static定义的变量值是上一次调用时候的值。

3.2、static修饰函数

在函数前面加static表示函数成为静态函数,表示该函数的作用域仅限于定义处到文件结尾。如果全局函数有一个函数名字和静态函数一样的名字,编译器不会报错,使用本文件的静态函数运行。

#include <stdio.h>static int j;void func1(void)
{static int i = 0;i++;printf("i = %d\n", i);
}void func2(void)
{j = 0;j++;printf("j = %d\n", j);
}int main(int argc, char *argv[])
{int k = 0;for(k = 0; k<10; k++){func1();func2();printf("\n");}return 0;
}

大家运行上面代码加深下对static的理解

 

4、大喇叭关键字----extern

上面有一个例子已经说到了extern,extern就像一个大喇叭一样,他不分配内存,就是不讨老婆,但是总是跟别人说,谁谁娶媳妇了,这个标识符就定义了,这个函数被定义了,如此如此,不过这个大喇叭非常有用,比如他可以跟编译器说,这个家伙已经讨老婆了,你可以用他生孩子了,就不要再让他二婚了。

既然extern不能给别人发结婚证,那么下面这个

extern int i = 10;

是否有问题?

不能发结婚证,就是不能分配内储存,没有内存怎么把10存下来?所以肯定是错的。

 

5、让cpu最累的关键字----volitile

volitile这个关键字让cpu非常累,每次运行到他的位置,都要去内存重新确定他的值,在中断的使用的变量最好用这个关键字修饰,因为中断的变量你不知道什么时候会被改变,volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。说白了就是不能让cpu偷懒,所以说是类似老大CPU了。

 

6、只能读的关键字----const

const可以理解为别人只能来读我的值,不能改变我,有的人写代码加上这个就是担心自己的值被改变,比如const int i =5;下一次,i =6;这就是有问题的,i 的值已经确定了,就像define一样(不过define不是关键字)。

/*************************************************************************> File Name: const.c> Author:           > Mail:             > Created Time: Mon 29 Oct 2018 02:33:19 PM CST************************************************************************/#include<stdio.h>       
#define M 3             
const int N = 5;        void main(void)         
{                       printf("%p\n",&N);int i = M;          int j = N;          printf("%p\n",&N);                                                                                                 int x = M;          int y = N;          printf("%p %p %p %p\n",&i,&j,&x,&y);printf("%d %d %d %d\n",i,j,x,y);
}         

7、不色不空的关键字----void

大家可以看看void 和void* ,谁是色,谁是空呢?void 表示这个是空的,什么都没有,比如void i; 我们定义一个空的i,这就有问题了,这个i编译器到底要不要给他分配空间呢?就是这样的情况,编译器报错了,你搞什么飞机给我一个空的东西还想让我给你讨老婆。

但是void 不一样,void *表示所有类型的指针,这就是色啊,女人都想入非非。

说明:既然提供了void的这两种用法,就去运用。即函数没返回值就将其返回值类型写为void,函数没有形参就将其形参写为void。不了解编译器默认操作时,不要依赖。即使了解其默认操作,也别依赖,因为肯定有人不了解的,这样别人就看不懂你的代码了。

大家看看这个是否正确

add(int a,int b)
{return (a+b);
}

下面两个函数就是用void*作为返回值

memcpy  

原型:extern void *memcpy(void *dest, void *src, unsigned int count);   

用法:#include   

功能:由src所指内存区域复制count个字节到dest所指内存区域。   

说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。   

注意:与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

 

memset

原型:extern void *memset(void *buffer, int c, int count);

用法:#include

功能:把buffer所指内存区域的前count个字节设置成字符c。

说明:返回指向buffer的指针。

8、return 关键字

return 关键字终止一个函数并返回一个值。

#include "stdio.h"add(int a,int b)
{return (a+b);
}char * str(void)
{char *strc = "This is c\n";return strc;
}main(void)
{printf("%d\n",add(1,4));printf("%s\n",str);return ;
}

看看上面这个函数的输出,会有陷阱的

9、柔性数组

讲了很多关键字,现在讨论一个酷的东西,以后也会经常用到,柔性数组是可以自由变化长度的数组,对开发上来说是非常有用的。

C99中,结构体的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构体的柔性数组成员前面必须至少一个其他成员。

#include<stdio.h>
typedef struct _SoftArray{int len;int array[];
}SoftArray;int main()
{int len = 10;printf("The struct's size is %d\n",sizeof(SoftArray));
}

我们可以看出,_SoftArray结构体的大小是4,显然,在32位操作系统下一个int型变量大小刚好为4,也就说结构体中的数组没有占用内存。为什么会没有占用内存,我们平时用数组时不时都要明确指明数组大小的吗?但这里却可以编译通过呢?这就是我们常说的动态数组,也就是柔性数组。

#include<stdio.h>
#include<malloc.h>
typedef struct _SoftArray{
int len;
int array[];
}SoftArray;
int main()
{int len=10,i=0;SoftArray *p=(SoftArray*)malloc(sizeof(SoftArray)+sizeof(int)*len);p->len=len;for(i=0;i<p->len;i++){p->array[i]=i+1;}for(i=0;i<p->len;i++){  printf("%d\n",p->array[i]);}free(p);return 0;
}

这代码的作用是用柔性数组动态创建数组并输出数组内容,这里我就直接解释解释这两句代码

   SoftArray* p = (SoftArray*)malloc(sizeof(SoftArray) + sizeof(int) *10);p->len = 10;

第一句,主要是根据你要定义的数组长度和数据类型以及柔性数组本身的大小来开辟一块内存空间给柔性数组,第二个是定义len的长度,便于确定循环打印输出

觉得对你有用,请关注微信公众号【嵌入式Linux】

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

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

相关文章

python bottle框架 运维_python bottle 框架实战教程:任务管理系统 V_1.0版 | linux系统运维...

经过1-2个星期的开发&#xff0c;现在用任务管理功能&#xff08;添加、删除、修改&#xff0c;详细&#xff09;、项目管理功能&#xff08;添加、删除&#xff0c;修改&#xff0c;详细&#xff09;等&#xff0c;我把现在完成的版本&#xff0c;叫做1.0吧。发布完这个版本后…

form 窗体增加边框_C#控件美化之路(13):美化Form窗口(上)

在开发中最重要的就是美化form窗口&#xff0c;在开发中&#xff0c;大多都是用会用自主美化的窗口开发程序。本文只是点多&#xff0c;分为上中下节。分段讲解。本文主要讲解窗口美化关键步骤。首先美化窗体&#xff0c;就需要自己绘制最大化 最小化 关闭按钮。其次就是界面样…

第四周数据结构

转载于:https://www.cnblogs.com/bgd150809329/p/6650255.html

gdb x命令_gdb基本命令

参考自&#xff1a;gdb基本命令(非常详细)_JIWilliams-CSDN博客_gdb命令​blog.csdn.net本文介绍使用gdb调试程序的常用命令。 GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。如果你是在 UNIX平台下做软件&#xff0c;你会发现GDB这个调试工具有比VC、BCB的图形化调试…

YOLOX-PAI: An Improved YOLOX, Stronger and Faster than YOLOv6

YOLOX-PAI&#xff1a;一种改进的YOLOX&#xff0c;比YOLOv6更强更快 原文&#xff1a;https://arxiv.org/pdf/2208.13040.pdf 代码&#xff1a;https://github.com/alibaba/EasyCV 0.Abstract We develop an all-in-one computer vision toolbox named EasyCV to facilita…

安装一直初始化_3D max 软件安装问题大全

纵使3D虐我千百遍&#xff0c;我待3D如初恋&#xff01;大家好&#xff0c;我是小文。快节奏生活的今天&#xff0c;好不容易有点学习的热情&#xff0c;打开电脑学习下&#xff0c;没想到被简单的软件安装问题浇灭&#xff01;这不是耽误了一位伟大的世界设计师诞生的节奏吗&a…

TCP/IP 协议栈 -- 编写UDP客户端注意细节

上节我们说到了TCP 客户端编写的主要细节&#xff0c; 本节我们来看一下UDP client的几种情况&#xff0c;测试代码如下&#xff1a; server&#xff1a; #include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h>…

RuntimeError: Address already in use

问题描述&#xff1a;Pytorch用多张GPU训练时&#xff0c;会报地址已被占用的错误。其实是端口号冲突了。 因此解决方法要么kill原来的进程&#xff0c;要么修改端口号。 在代码里重新配置 torch.distributed.init_process_group()dist_init_method tcp://{master_ip}:{mast…

Windows环境下的安装gcc

Windows具有良好的界面和丰富的工具&#xff0c;所以目前linux开发的流程是&#xff0c;windows下完成编码工作&#xff0c;linux上实现编译工作。 为了提高工作效率&#xff0c;有必要在windows环境下搭建一套gcc,gdb,make环境。 MinGW就是windows下gcc的版本。 下载地址ht…

RuntimeError: NCCL error in:XXX,unhandled system error, NCCL version 2.7.8

项目场景&#xff1a; 分布式训练中遇到这个问题&#xff0c; 问题描述 大概是没有启动并行运算&#xff1f;&#xff1f;&#xff1f;&#xff08; 解决方案&#xff1a; &#xff08;1&#xff09;首先看一下服务器GPU相关信息 进入pytorch终端&#xff08;Terminal&#x…

一张倾斜图片进行矫正 c++_专业性文章:10分钟矫正骨盆前倾

如今&#xff0c;骨盆前倾(又称“下交叉综合征”)非常多&#xff0c;大部分是由于以下两个原因而变得越来越突出&#xff1a;经常久坐不良的运动习惯后面我们讲到纠正骨盆前倾的四个基本步骤&#xff0c;让你快速解决&#xff0c;提高生活质量知识型和系统型的内容&#xff0c;…

TypeError: can‘t convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory

项目场景&#xff1a; 运行程序&#xff0c;出现报错信息 TypeError: cant convert CUDA tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.。 Traceback (most recent call last):File "tools/demo.py", line 97, in <module>vi…

Secure CRT 自动记录日志

配置自动log操作如下&#xff1a; 1.options ---> Global Options 2、General->Default Session->Edit Default Settings 3、Terminal->Log File 设置如图上所示 点击 日志 &#xff0c;在选项框中 Log file name中填入路径和命名参数&#xff1a; E:\Log\%Y_%M_…

java 异步调用方法_乐字节Java编程之方法、调用、重载、递归

一、概述方法是指人们在实践过程中为达到一定目的和效果所采取的办法、手段和解决方案。所谓方法&#xff0c;就是解决一类问题的代码的有序组合&#xff0c;是一个功能模块。编程语言中的方法是组合在一起来执行操作语句的集合。例如&#xff0c;System.out.println 方法&…

git clone 从GitHub上下载项目到服务器上运行+创建虚拟环境

1. 基础的Linux命令 可先进入需要放置文件的路径之下 pwd # 可看当前路径 cd …/ #返回上一层目录 cd ./xx/ #进入当前路径下的下一个文件2. GitHub项目clone到服务器上运行 # 复制GitHub页面的链接&#xff0c;在服务器后台输入git clone 命令即可 git clone https://githu…

java 调用python_Java平台如何调用Python平台?

1. 问题描述Java平台要调用Pyhon平台已有的算法&#xff0c;为了减少耦合度&#xff0c;采用Pyhon平台提供Restful 接口&#xff0c;Java平台负责来调用&#xff0c;采用HttpJson格式交互。2. 解决方案2.1 JAVA平台侧2.1.1 项目代码public static String invokeAlgorithm(Strin…

C 实现 删除字符串空白符的函数 strtrim

说在前面的话 字符串操作在很多C语言比赛里面都有涉及&#xff0c;最近公众号里面的C语言比赛&#xff0c;都是两个关于字符串操作的题目&#xff0c;希望大家认真看题目。 直接上代码 /*************************************************************************> Fil…

javascript犀牛书_犀牛书作者:最该忘记的JavaScript特性

作者&#xff1a; 李松峰转发链接&#xff1a;https://mp.weixin.qq.com/s/guAN1Cz2gYfKdBhmUpLyVA前言JavaScript这门语言的第一个演示版差不多就在25年前诞生。没记错的话&#xff0c;25年前的今天&#xff0c;1995年5月10日&#xff0c;星期三&#xff0c;我刚刚过了创造Jav…

Weblogic(4)—— Linux环境Weblogic12c配置节点管理(nodemanage.properties)来开启应用服务器(server)及线程池配置...

Linux环境搭建weblogic12c服务器&#xff0c;用来进行weblogic服务器项目部署&#xff0c;刚创建weblogic服务器会默认存在AdminServer管理服务器。但是项目应用一般是不能挂在这个服务器上的&#xff0c;需要自己单独创建应用服务器。 使用root权限登录 服务器&#xff1a; 输…

IDEA与Maven安装+IDEA中利用maven自动下载第三方Jar包

Maven详细安装教程_慕之寒的博客-CSDN博客_maven安装一、安装apache官网下载需要的版本&#xff0c;然后解压缩&#xff0c;解压路径尽量不要有空格和中文Maven – Download Apache Mavenhttps://maven.apache.org/download.cgi二、配置环境变量新建 系统变量变量名&#xff1a…