【零天赋C语言】——初识关键词static,#define定义常量和宏,指针,结构体

目录

一、关键词static

修饰局部变量-称为静态局部变量

修饰全局变量-称为静态全局变量

修饰函数-称为静态函数

二、#define定义常量和宏 

#define定义常量

#define定义宏 

 三、初识指针

四、初识结构体


一、关键词static

在C语言中:
static是用来修饰变量和函数的
1. 修饰局部变量-称为静态局部变量
2. 修饰全局变量-称为静态全局变量
3. 修饰函数-称为静态函数

  • 修饰局部变量-称为静态局部变量

下面这行代码结果是多少呢?

#include <stdio.h>
void test()
{
	int n = 1;
	n++;
	printf("%d ", n);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	printf("\n");
	return 0;
}

结果如下:

加了static修饰后的局部变量n:

#include <stdio.h>
void test()
{
	static int n = 1;
	n++;
	printf("%d ", n);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}
	printf("\n");
	return 0;
}

那结果是多少呢?

看到这里是不是有些同学会感到疑惑:为什么加了static修饰之后代码会变成这样?

stastic到底是个什么东西?怎么用啊?

 

要想完全理解,我们首先需要知道内存的划分和管理:

 第一个代码中创建的局部变量    int n = 1 储存在栈区,其生命周期是:
void test()
{
    int n = 1;
    n++;
    printf("%d ", n);
}

从调用  test()函数开始,到  test()函数结束,每次调用时创建,结束时销毁,所以打印的结果时是十个2。

但是当第二个代码中的局部变量被  static  修饰时,改变了局部变量的储存类型,原本局部变量是储存在栈区的,经过   static   修饰后该局部变量储存在了静态区,储存在静态区的变量出了它的作用域时不会销毁 ,其生命周期与程序的生命周期相同,但其作用域不变。所以,第二个代码打印出来的是2到11。

  • 修饰全局变量-称为静态全局变量

用下图代码理解一下全局变量:

extern是用来声明外部符号的;

由上图代码可以看出:全局变量具有外部链接属性。

但当全局变量被static修饰时:

 由此可以得出:static修饰全局变量时,改变了全局变量的链接属性;

本来一个全局变量是具有外部链接属性的,但被static修饰之后就变成了内部连接属性,这时,被static修饰的全局变量只能在本源文件(.c)中使用,其它文件无法在使用到。

  • 修饰函数-称为静态函数

用下图代码理解一下函数:

extern是用来声明外部函数的;

但当函数被static修饰时:

代码会报错,由此可以得出:

static修饰函数和修饰全局变量是类似的,一个函数本来是具有外部链接属性的,但是当函数被static修饰时,外部链接属性就变成了内部连接属性,函数就只能在本源文件中使用,不能在外部文件中使用了。

二、#define定义常量和宏 

  • #define定义常量

#define NUM 100
#define STR "hehe"
#include <stdio.h>
int main()
{
	printf("%d\n", NUM);//printf("%d\n", 100);
	printf("%s\n", STR);//printf("%s\n", "hehe");

	return 0;
}

运行的结果为:

  • #define定义宏 

#define  ADD(x,y) ((x)+(y))
#include <stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	int sum = ADD(a, b);//int sum = (a+b);
	printf("%d\n", sum);

	return 0;
}

特别注意:ADD(x,y)((x)+(y))后面表达式的两个变量必须分别用括号括起来;

运行的结果为:

 三、初识指针

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址,而指针即为地址。

 内存单元有编号(地址/指针)

*pa:通过  这个解引用操作符找到pa这个指针变量所储存的地址的所指向的对象——a,

然后再对a进行赋值。

思考下面的代码:

#include <stdio.h>
int main()
{
	char ch = 'w';
	int n = 100;
	double d = 3.14;

	char* pc = &ch;
	int* pi = &n;
	double* pd = &d;

	printf("%d\n", sizeof(pc));
	printf("%d\n", sizeof(pi));
	printf("%d\n", sizeof(pd));

	return 0;
}

结果是:

 为什么 char类型的变量、int类型的变量和double类型的变量所打印的结果一样呢?

因为pc、pi、pd都是指针变量,而指针变量是储存地址的,地址的存放需要多大的空间,指针变量的大小就应该是多大。

并且32位机器 - 支持32位虚拟地址空间 - 产生的地址就是32bit位 -需要32bit的空间存储4byte - 指针变量的大小是4byte;

64位机器 - 支持64位虚拟地址空间 - 产生的地址就是64bit位 -需要64bit的空间存储8byte - 指针变量的大小是8byte 

由于我的是32位的,所以结果为4。

四、初识结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。
这里只能使用结构体来描述了。
例如:

描述一个学生
创建的一个学生类型

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	double score;
};

int main()
{
    struct Stu s1 ;
	scanf("%s %d %s %lf", s1.name, &(s1.age), s1.sex, &(s1.score));

	//结构成员访问操作符
	//结构体变量.结构体成员

	struct Stu * ps = &s1;

	//printf("%s %d %s %lf\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).score);
	printf("%s %d %s %lf\n", ps->name, ps->age, ps->sex, ps->score);

	//-> 结构成员访问操作符
	//结构体指针->结构体成员
	
	return 0;
}

注:输入结构体中数组时不能写成   (&数组名),因为数组名本身就表示了数组首元素的地址,再加上一个  &  的话,表示的是整个数组的地址,产生歧义,虽然有时候写成(&数组名)运行的结果是正确的,但是这样写一点也不严谨,未来面试考试的话都是会扣分的!!

最后共勉:

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值