简单点-c-lesson4(关键字static、#define和指针)

1.关键字static

关键字:
char float int long short double signed unsigned continue
break case default do else goto if switch while return void typedef
union volatile auto static struct const enum extern register sizeof

static:修饰局部变量、全部变量、函数

修饰局部变量(局部变量也称临时变量,自动变量)

情况1:局部变量—输出10个1

#if 0
#include <stdio.h>
#include <windows.h>
void Show(){
	int i = 0;
	++i;
	printf("%d\n",i);
	//printf("%d %p\n",i,&i);
}
int main(){
	int i = 0;
	for(; i<10; i++){
		Show();
		Sleep(500);
	}
	system("pause");
	return 0;
}
#endif

在这里插入图片描述
在这里插入图片描述

情况2:static局部变量—输出1,2,3,4,5,6,7,8,9,10

#if 0
#include <stdio.h>
#include <windows.h>
void Show(){
	static int i = 0;
	++i;
	printf("%d\n",i);
}
int main(){
	int i = 0;
	for(; i<10; i++){
		Show();
		Sleep(500);
	}
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

情况1和情况2结论:
static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,直到程序结束,生命周期才结束 。
注:作用域没变,生命周期改变—局部变量类似转变为全局变量

补充:初始化和赋值,上次博客有详细的介绍。
(1)初始化:int x =10; 变量只能初始化一次;
(2)赋值:x = 20;x = 200;变量可以被多次赋值。

修饰全局变量

情况3:单文件全部变量 — 100

#if 0
#include <stdio.h>
#include <windows.h>
int g_value = 100;
int main(){

	printf("%d\n",g_value);//100
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

情况4:static单文件全部变量 — 100

#if 0
#include <stdio.h>
#include <windows.h>
static int g_value = 100;
int main(){

	printf("%d\n",g_value);//100
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

情况3和情况4结论:
(1)全局变量在单个文件中时,即同一个源文件时,用不用static,都可以访问全局变量。
(2)static修饰的此种全部变量情况结果不明显。—多个源文件进行验证

情况5:多个文件中全部变量 — 100

//t.c源文件
#if 0
#include <stdio.h>
#include <windows.h>

//第三方变量进行声明
//定义只能定义(开辟空间和放置内容)一次,声明可以声明多次(声明是告诉你这个东西已经存在。)
extern int g_value;//extern 类型+变量名

int main(){
	printf("%d\n",g_value);//100
	system("pause");
	return 0;
}
#endif
//t1.c源文件
int g_value = 100;//定义全局变量

在这里插入图片描述

情况6:static多个文件中全部变量 —报错

#if 0
#include <stdio.h>
#include <windows.h>

//第三方变量进行声明
//定义只能定义(开辟空间和放置内容)一次,声明可以声明多次
extern int g_value;

int main(){
	printf("%d\n",g_value);//100
	system("pause");
	return 0;
}
#endif
//情况6:static多个文件中全部变量 --- 100
static int g_value = 100;

运行后报错:1>t.obj : error LNK2001: 无法解析的外部符号 “int g_value” (?g_value@@3HA)
在这里插入图片描述
情况5和情况6结论:
(1)全部变量支持跨文件访问:extern int g_value;
(2)static修饰全部变量,代表该全部变量,只在本源文件中有效,只能在本源件中访问,不能在其他源文件中进行访问
(3)在本文件中加不加static均可以访问。

修饰函数

情况7:函数 — 10个12345678

#if 0
#include <stdio.h>
#include <windows.h>

//函数声明
extern void Show();

int main(){
	Show();
	system("pause");
	return 0;
}
#endif
//情况7:函数
void Show(){
	static int i = 0;
	for(; i<10; i++)
	printf("12345678\n");
}

在这里插入图片描述
情况8:static修饰函数 —报错

#if 0
#include <stdio.h>
#include <windows.h>

//函数声明
extern void Show();
int main(){
	Show();
	system("pause");
	return 0;
}
#endif
//情况8:static函数
static void Show(){
	static int i = 0;
	for(; i<10; i++)
	printf("12345678\n");
}

static修饰函数,运行后报错,1>t.obj : error LNK2019: 无法解析的外部符号 “void __cdecl Show(void)” (?Show@@YAXXZ),该符号在函数 _main 中被引用
在这里插入图片描述
情况7和情况8结论:
(1)同情况5和情况6,static修饰函数和修饰全局变量类似。
(2)函数访问支持跨文件的,需要extern声明;
(3)static修饰函数,该函数只在本文件内被调用和访问,不能跨文件访问
(4)同一个源文件,用不用static,均可以访问函数。

情况9:多个源文件时,可通过函数来间接访问static修饰的全局变量

(1)全局变量用static修饰;
(2)函数不能用static修饰;
(3)需要在其他源文件中声明函数和全局变量,使用extern关键字

#if 0
#include <stdio.h>
#include <windows.h>

//函数声明
extern void Show();
extern int g_value;
int main(){
	Show();
	system("pause");
	return 0;
}
#endif
//情况9:static全部变量和函数可以进行间接被访问
static int g_value = 100;
void Show(){
	static int i = 0;
	for(; i<10; i++)
	printf("hello:%d\n",g_value);
}

在这里插入图片描述

2.define

#define定义常量和宏
(1)只做简单的文本替换 ,对单独使用的变量而言,字符串,变量中出现大的不做替换。
(2)好处:便于代码的维护性 ;方便阅读,能做到见名知意。
(3)但是不建议做简单运算时使用宏,因为在运算时进行文本替换,容易出错。并且宏是在运算前就进行文本替换,不做任何的计算。
(4)要想正确使用宏,给宏中的每个参数都带上括号。
eg:#define DOUBLE(x) ((x)+(x))

#if 0
#include <stdio.h>
#include <windows.h>

#define M 1234

int main(){
	int x = M;
	printf("%d\n",x);
	printf("%d\n",M);
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

宏函数

#if 0
#include <stdio.h>
#include <windows.h>
#define DOUBLE(x) x*x //"宏函数"
int main(){
	printf("%d\n",DOUBLE(10));//类似函数,但不同于函数
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

宏函数易出错的一个点

#if 0
//#define 易错 --- 只替换文本 -- 并且在编译阶段
#include <stdio.h>
#include <windows.h>
#define DOUBLE(x) (x)*(x) //"宏函数" ---121
#define DOUBLE(x) x*x //"宏函数" ---21

int main(){
	printf("%d\n",DOUBLE(10 + 1));//类似函数,但不同于函数
	printf("%d\n",DOUBLE(10 + 1));//类似函数,但不同于函数
	system("pause");
	return 0;
}
#endif

在这里插入图片描述
举个栗子:

#if 0
#include <stdio.h>
#include <windows.h>

#define DOUBLE(x) x+x

int main(){
	printf("%d\n",10 * DOUBLE(10 + 1));//112
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

#if 0
#include <stdio.h>
#include <windows.h>

#define DOUBLE(x) (x+x)

int main(){
	printf("%d\n",10 * DOUBLE(10 + 1));//220
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

针对上述问题,提出的解决办法:每个参数都带括号

#if 0
#include <stdio.h>
#include <windows.h>

#define DOUBLE(x) ((x)*(x))

int main(){
	//10*DOUBLE(10+1) 10*((10+1)*(10+1)) = 1210
	printf("%d\n",10 * DOUBLE(10 + 1));//1210
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

3.指针

1、why要有指针:
具有很强的指向意性,方便快速找到内存中对应的字节位置,以此提高查找效率

2、 编号/编址:就是对内存中的每个小单元进行连续的编号; (相当于给内存赋上门牌号)
(1)计算机是32位:则有 2^32 个小单元;计算机是64位,则有 2^64 个小单元.
(2) 编址:硬件电路自动完成的
(3)访问内存的最基本单元是字节
(4)编址采取的规则:连续的编址(内存空间的编号就是地址),快速查找,以此提高查找速率。
注:计算机32位,2^32*1字节 = 2^10 * 2^10 * 2^10 * 2^2 = 1k *1k *1k * 4 = 4G
在这里插入图片描述

3、计算机有CPU、内存、硬盘
(1)定义变量,全部都是在内存中定义或者开辟的;
(2)XX.exe文件存在在硬盘中,双击时,就是将.exe程序加载到内存;
(3)内存中存放的是我们写的代码块;
(4)能运行,说明已经加载到内存了。
在这里插入图片描述

4、what指针?
eg:int* p = &a;
(1)指针变量:是一个变量,只不过存放的内容是指针,类型为指针。比如这里就是p是指针变量,存放的是变量a的地址。
(2)地址是数据;地址可以放在一个空间里。比如a的地址(右值)是一个数据,a的地址可以存放在指针变量p(右值)的空间中。地址可以放在指针变量中
(3)能定义的一定是变量,
int x;定义一个变量;
int *p;定义一个指针变量;
(3)要开辟四个字节(32位计算机)或者八个字节(64位计算机)的空间。
(4)指针:地址
注:内存中空间的编号叫做“地址”—“指针”

注:指针VS指针变量
指针是地址;
指针变量是一个变量,该变量里面的内容是指针。

在这里插入图片描述

5、左值:代表一个变量的空间;int a = 10;用的是a的空间。
右值:代表一个变量的内容;int b = a;用的是a的内容。

6、对指针进行解引用,代表的是指针所指向的变量,但具体用的是变量的内容还是变量的空间,取决于变量是左值还是右值

指针的理解

#if 0
#include <stdio.h>
#include <windows.h>

int main(){
	int a = 10;
	//p是指针变量,要开辟空间,地址是数据,地址可以存放在p中。
	//一般说p指向a
	int* p = &a;
	printf("%p %p %d %d",&a,p,a,*p);
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

变量赋值

#if 0
#include <stdio.h>
#include <windows.h>

int main(){
	int a = 10;//变量的空间存10
	a = 20;//变量的空间赋值20
	int b = a;//将变量的内容给b
	printf("%d %d",a,b);
	system("pause");
	return 0;
}
#endif

在这里插入图片描述
在这里插入图片描述

关于不同的指针变量代表的不同的涵义

#if 0
#include <stdio.h>
#include <windows.h>

int main(){
	int a = 10;//变量的空间存10
	int b = 20;
	int* p = &a;
	p = &b;//p代表变量空间: 变量
	int* q = p;//p代表变量内容: 地址
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

引用 和 &的引用*

#if 0
#include <stdio.h>
#include <windows.h>

int main(){
	int a = 10;                
	int* p = &a;
	int b;
	//&a,p ---- p指针变量就是a的地址
	//a,*p ---- p解引用就是a的内容
	//*是解引用,即*p就是a的内容 ----    *p == a

	printf("%p,%p,%d,%d\n",&a,p,a,*p);

	//*p ==  a
	*p = 20; //左值代表a的空间
	b = *p;  //右值代表a的内容
	printf("%d %d\n",a,b);
	system("pause");
	return 0;
}
#endif

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

不管什么类型的指针,32位计算机,4byte;64位计算机,8byte

#if 0
#include <stdio.h>
#include <windows.h>

int main(){
	printf("%d\n",sizeof(int*));
	printf("%d\n",sizeof(short*));
	printf("%d\n",sizeof(double*));
	printf("%d\n",sizeof(float*));
	printf("%d\n",sizeof(char*));
	printf("%d\n",sizeof(long long*));
	printf("%d\n",sizeof(long*));
	printf("%d\n",sizeof(byte*));
	printf("%d\n",sizeof(int******************));

	system("pause");
	return 0;
}
#endif

在这里插入图片描述
结论:指针大小,在32位平台是4个字节,在64位平台是8字节。

往期博客:
简单点-c-lesson1
简单点-c-lesson2
简单点-c-lesson3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值