当前位置: 首页 > news >正文

关键字 - 第二讲

本节重点

  • 在多文件中,关于全局变量和函数的一些结论

  • static的作用

  • 如何看待类型

  • 变量的命名规则

  • sizeof的理解

1.3 最名不符实的关键字 - static

先建立2个源文件进行验证,然后提炼出头文件存在的必要性。

认识多文件 - 补充内容

// test.c
int g_val = 10;void show()
{printf("hello files!\n");
}// main.cextern int g_val = 100;// 不可以!声明并没有开辟空间,"=100"叫做初始化!!!但是也不会报错,编译器会自动忽略掉!!!int main()
{show();//会告警!!!system("pause");return 0;
}

test.c 源文件中定义了一个全局变量和一个全局函数;

main.c使用了上面的数据,如果后面有其他的很多源文件也想要使用test.c 中的数据,我们真的要全部声明吗,还有对于函数还会告警的!我们还是需要对函数进行声明的 --- 函数声明这里先放一放。

单纯的使用源文件,组织项目结构结构的时候,项目越大,越复杂的时候,我们的维护成本就会越来越高,为了解决这种问题 --- 头文件出来了!!!(好好看下面代码的注释!!!)

// h: 我们称之为头文件,一般包含函数声明,变量声明,宏定义,头文件等内容(header)
// c: 我们称之为源文件,一般包含函数实现,变量定义等(.c:c语言)// test.h
#pragma once    //防止头文件被重复包含,当前只需要记住,后面会无数次用#include <stdio.h>
#include <windows.h>extern int g_val;// 这个必须带上extern,防止二义性:看成是的定义了
//在 C 语言中,extern 用于声明外部变量(即其他文件中定义的全局变量)void show();
// C 语言的一个特性:函数声明默认具有外部链接性,不需要显式加extern关键字,编译器也会将其视为外部函数(可以被其他文件调用)。//所以在头文件中声明函数时,通常省略extern,写成void show();即可,这是 C 语言的惯例写法。//如果写成extern void show();也完全正确,只是多余的,不会影响程序功能。 --- 建议带上extern//怎么定义就怎么声明,不要一个带参,一个不带参!!!// test.c
#include "test.h" //""包含头文件,目前只需要知道是自己写的头文件,就用""包含即可int g_val = 10;void show()
{printf("hello files!\n");
}// main.c
#include "test.h" //同上int main()
{printf("hello files!\n");system("pause");return 0;
}

全局变量和函数的两个结论 - 补充内容

我们要了解 static ,有几个结论是需要认知清楚的:

变量可以跨文件访问吗?

函数可以跨文件访问吗?

答:

全局变量,是可以跨文件,被访问的。

全局函数,是可以跨文件,被访问的。

这是为什么???

有一定规模的项目,一定是多文件的,多个文件至之间,后续一定要进行数据交互(#include"test.h", main.c -> test.c 函数)如果不能跨文件,交互成本就会比较高,所以设计成全局的化,就可以跨文件访问!

在具体的应用场景,有没有可能,我们不想要让全局变量或者函数跨文件访问,而只想在本文件内部被访问???

这就需要我们的static

1.3.1 修饰变量

修饰全局变量,该全局变量只能在本文件内被使用,不能被外部其他文件直接访问,但是可以是间接的,比如说通过内部的函数带出来。

总结:static修饰全局变量,影响的是作用域的概念,函数类似。而生命周期是不变的。

//test.h文件
void fun1()
{int i = 0;i++;printf("no static: i=%d\n", i);
}
void fun2()
{static int i = 0;i++;printf("has static: i=%d\n", i);
}//main.c文件
int main()
{for (int i = 0; i < 10; i++) {fun1();fun2();}system("pause");return 0;
}
  • 结论:static修饰局部变量,变量的生命周期变成全局周期 --- 随进程了(作用域---{}内不变

  • 另外,这里需要初步讲一下:初始化与赋值的概念。

有些误导性
第1个作用:修饰变量。变量又分为局部变量和全局变量,但它们都存在内存的静态区。
关于C存储布局,我们后面讲到函数会整体来讲,这里不赘述。

static 我们可以理解成为项目维护提供安全保证的!!!

1.3.2 修饰函数

修饰函数,该函数只能在本文中内被使用。

static修饰函数,该函数只能被本文件内被访问,不能被外部文件直接访问,也是同样的道理!

static void fun3()
{static int i = 0;i++;printf("has static: i=%d\n", i);
}void fun3_helper()
{fun3();
}//main.c文件
int main()
{for (int i = 0; i < 10; i++) {fun3();fun3_helper();}system("pause");return 0;
}

1.4 基本数据类型

经过前面的练习,相信同志们对于定义变量并不陌生了。那么此处,我们讲一些其他内容便于大家理解类型。

目前我们只讲内置类型,其他类型我们后面慢慢展开。

C 数据类型

基本类型
数值类型
字符串类型char
数组
结构体struct
共用体union
指针类型
枚举类型emurn
空类型void短整型short
整型int
长整型long
单精度型float
双精度型double

1.4.1 数据类型与"模子"

C常见内置类型:

char
short
int
long
long long
float
double

如何看待数据类型:

前面已经说过,定义变量的本质:在内存中开辟一块空间,用来保存数据。

而定义一个变量,是需要类型的,这个是基本语法决定的。那么,类型决定了:变量开辟空间的大小。

#include <stdio.h>
#include <windows.h>int main()
{//sizeof简单介绍,下个主题就讲printf("%d\n", sizeof(char));    //1printf("%d\n", sizeof(short));    //2printf("%d\n", sizeof(int));    //4printf("%d\n", sizeof(long));    //4printf("%d\n", sizeof(long long));    //8printf("%d\n", sizeof(float));    //4printf("%d\n", sizeof(double));    //8system("pause");return 0;
}

在继续讨论之前,我有一个问题:为什么要根据类型,开辟一块空间,直接将内存整体使用不好吗?

不好。

任何时刻,都不是你一个程序在运行,还有很多其他程序也在运行。你整块用了,让别人怎么办?
另外,你会都用了,一定需要在任何时刻,全部都用完吗?对于暂时不用,但是给你了,对计算机来讲,就是浪费。

那么,问题又来了,我使用部分内存,使用多少由什么决定?其实是由你的场景决定,你的计算场景,决定了你使用什么类型的变量进行计算。你所使用的类型,决定了你开辟多少字节的空间大小。

所以,C语言中,为什么会有这么多的类型?就是为了满足不同的计算场景。

比如,整形计算,字符计算,字符串计算,浮点数计算等。

然后,在回归到书中,关于"模子"的介绍。为了不让同志们感到不适,找了张图。

1.4.2 变量命名规则

min-length && max-information --- 最短长度,最大信息

【规则 1-1】 推荐
【规则 1-2】 推荐
【规则 1-3】 推荐,这个叫做大驼峰命名,具体我看看情况进行对变量命名
【规则 1-4】 推荐
【规则 1-5】 推荐,目前,全局变量可以在变量名前带0...以表示全局含义
【规则 1-6】 暂时不推荐,我们目前关于命名、简单的来
【规则 1-7】 部分推荐,了解一下,目前只要知道全局命名的级别则即可
【规则 1-8】 部分推荐,了解一下
【规则 1-9】 部分推荐,了解一下
【规则 1-10】 推荐
【规则 1-11】 推荐
【规则 1-12】 推荐
【规则 1-13】 推荐
【规则 1-14】 暂时不看,我们后面用的时候再说
【规则 1-15】 推荐
【规则 1-16】 了解
【规则 1-17】 不推荐,还是要看具体场景,转义后面说//目前要求:数字字母下划线,见名知意

记住大驼峰小驼峰,蛇形命名法基本,还有上面的要求就好了!

1.5 最冤枉的关键字 sizeof 理解

1.5.1 常年被误认为函数

int main()
{int a = 10;printf(%d\n,sizeof(a));// 1printf(%d\n,sizeof(int));// 2printf(%d\n,sizeof a);// 3printf(%d\n,sizeof int);// 4return 0;
}

这里那些序号是正确的呢?

4肯定是错的,sizeof 是一个关键字,一个关键字不能直接去求另一个特定的关键字的大小,不带()是不成立的!

那么1,2,3是不是对的呢?是的!sizeof 求特定的一种类型开辟空间的大小是直接有三种做法的!

第三种是可行的,这也就直接证明了 sizeof 不是函数!是关键字/操作符!!!

1.5.2 sizeof(int)*p 表示什么意思

这涉及到指针和数组的区别!

后续再谈!

http://www.dtcms.com/a/319732.html

相关文章:

  • Spring AI + Redis:构建高效AI应用缓存方案
  • 【物联网】基于树莓派的物联网开发【25】——树莓派安装Grafana与Influxdb无缝集成
  • 在 Linux 系统上安装 Docker 的步骤如下(以 Ubuntu/Debian为例)
  • 前缀和
  • 简洁明了的讲明什么是哈希(hash)函数
  • [激光原理与应用-170]:测量仪器 - 能量型 - 光功率计的工作原理与内部功能模块组成
  • 【第7话:相机模型3】自动驾驶IPM图像投影拼接技术详解及代码示例
  • 直连微软,下载速度达18M/S
  • Mysql 单行函数 聚合函数
  • MySQL聚簇索引与非聚簇索引详解
  • 北京企业数据防泄漏指南:5款适合北方市场的安全加密工具评测
  • 【华为机试】332. 重新安排行程
  • MySQL——黑马
  • STM32U5 周期性异常复位问题分析
  • 【MyQSL】库 表—基操
  • 性能优化——GPU的影响
  • [C++20]协程:语义、调度与异步 | Reactor 模式
  • Kafka原理--主题、分区、消费者的关系
  • windows内核研究(内存管理-线性地址的管理)
  • 【PHP 中的 `use` 关键字完全指南】
  • Linux图文理解进程
  • fiddler实用用法,抓包内容导入到apipos
  • 数据库管理系统:入门需要了解的内容
  • Modbus核心参数,调试工具,接线注意事项
  • Mongodb常用命令简介
  • C++线程库的学习
  • 从Centos 9 Stream 版本切换到 Rocky Linux 9
  • MongoDB数据存储界的瑞士军刀:cpolar内网穿透实验室第513号挑战
  • IDEA-Research推出的一系列检测、分割模型:从DINO(改进版DETR)、Grounding Dino、DINO-X到Grounded SAM2
  • 串联所有单词的子串-leetcode