关键字 - 第二讲
本节重点
在多文件中,关于全局变量和函数的一些结论
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 表示什么意思
这涉及到指针和数组的区别!
后续再谈!