初始C语言(三)

初始C语言(三),第1张

这里写自定义目录标题
    • 12. 常见关键字(32个)
      • 12.1 关键字 typedef
      • 12.2 关键字static
        • 12.2.1 修饰局部变量
        • 12.2.2 修饰全局变量
        • 12.2.3 修饰函数
      • 12.3 关键字register
    • 13. #define 定义常量和宏
    • 14. 指针
      • 14.1 内存
      • 14.2 指针变量的大小
    • 15. 结构体

12. 常见关键字(32个)
auto  break  case  char  const  continue  default  do
double else  enum extern float for goto  if  int  
long  register   return  short  signed sizeof  static 
struct  switch typedef union  unsigned  void  volatile  while
12.1 关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。


比如:

//将unsigned int 重命名为uint, 所以uint也是一个类型名
typedef unsigned int uint;

int main()
{
	//观察num1和num2,这两个变量的类型是一样的
	unsigned int num1 = 0;
	uint num2 = 1;

	return 0;
}
12.2 关键字static

在C语言中:
static是用来修饰变量和函数的

  1. 修饰局部变量 - 称为静态局部变量
  2. 修饰全局变量 - 称为静态全局变量
  3. 修饰函数 - 称为静态函数
12.2.1 修饰局部变量

代码1:不加static修饰

void test()
{
	int a = 1;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}

	return 0;
}


结果:打印出10个2。


代码2:加static修饰

//代码2
void test()
{
	static int a = 1;
	a++;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		i++;
	}

	return 0;
}


结果:打印2到11。


结论:

static修饰局部变量的时候,局部变量出了作用域,是不销毁的。


本质上,static修饰局部变量的时候,改变了变量的存储位置。


影响了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。


12.2.2 修饰全局变量

代码1:

//add.c
//全局变量
int g_val = 2022;


//test.c
//声明外部符号
extern int g_val;

int main()
{
	printf("%d\n", g_val);

	return 0;
}

代码2:

//add.c
//全局变量
static int g_val = 2022;


//test.c
//声明外部符号
extern int g_val;

int main()
{
	printf("%d\n", g_val);

	return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。


结论:

  1. 全局变量是具有外部链接属性的。


  2. static修饰全局变量的时候,这个全局变量的外部链接属性就变成了内部链接属性,其他源文件(.c)就不能再使用这个全局变量了。


  3. 一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。


12.2.3 修饰函数
//add.c
int Add(int a, int b)
{
	return a + b;
}


//test.c
extern int Add(int a, int b);

int main()
{
	printf("%d\n", Add(2, 3));

	return 0;
}

//add.c
static int Add(int a, int b)
{
	return a + b;
}


//test.c
extern int Add(int a, int b);

int main()
{
	printf("%d\n", Add(2, 3));

	return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。


结论:

一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。


12.3 关键字register

这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率。


注意是尽可能,不是绝对。


其实,CPU主要是负责进行计算的硬件单元,但是为了方便运算,一般第一步需要先把数据从内存读取到CPU内,那么也就需要CPU具有一定的数据临时存储能力。


注意:CPU并不是当前要计算了,才把特定数据读到CPU里面,那样太慢了。


所以现代CPU内,都集成了一组叫做寄存器的硬件,用来做临时数据的保存。


距离CPU越近的存储硬件,速度越快。


寄存器的认识

只要知道CPU内集成了一组存储硬件即可,这组硬件叫做寄存器。


寄存器存在的本质

寄存器存在的本质

在硬件层面上,提高计算机的运算效率。


因为不需要从内存里读取数据啦。


register 修饰变量

尽量将所修饰变量,放入CPU寄存区中,从而达到提高效率的目的。


那么什么样的变量,可以采用register呢?

  1. 局部的(全局会导致CPU寄存器被长时间占用)
  2. 不会被写入的(写入就需要写回内存,后续还要读取检测的话,register的意义在哪呢?)
  3. 高频被读取的(提高效率所在)
  4. 如果要使用,请不要大量使用,因为寄存器数量有限
  5. 就是register修饰的变量,不能取地址(因为已经放在寄存区中了嘛,地址是内存相关的概念)
int main()
{
	//寄存器变量
	register int num = 3;	//建议(无法绝对,由编译器决定)将3放到寄存器中

	return 0;
}
13. #define 定义常量和宏
//define定义标识符常量
#define MAX 1000

//define定义宏
#define ADD(x, y) ((x)+(y))

int main()
{
	int sum = ADD(2, 3);
	printf("sum = %d\n", sum);

	sum = 10 * ADD(2, 3);
	printf("sum = %d\n", sum);

	return 0;
}

14. 指针 14.1 内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。


所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。


为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地
址。


变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。


int main()
{
	int num = 10;
	&num;//取出num的地址
	//注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)

	printf("%p\n", &num);//打印地址,%p是以地址的形式打印

	return 0;
}

那地址如何存储,需要定义指针变量

int main()
{
	int num = 10;	//向内存申请4个字节,存储10

	//&:取地址 *** 作符
	int* p = &num;	
	//p为一个整形指针变量
	
    *p = 20;
	//*:解引用 *** 作符
	printf("%d\n", *p);	//通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象

	return 0;
}

14.2 指针变量的大小
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
	printf("%d\n", sizeof(char*));
	printf("%d\n", sizeof(short*));
	printf("%d\n", sizeof(int*));
	printf("%d\n", sizeof(double*));
	return 0;
}

结论:

指针大小在32位平台是4个字节,64位平台是8个字节。


15. 结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。


比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。


这里只能使用结构体来描述了。


例如:

struct Stu
{
	char name[20];	//名字
	int age;	//年龄
	char sex[5];	//性别
	char id[15];	//学号
};

结构体的初始化:

int main()
{
	//结构体的初始化
	struct Stu s = { "张三", 20,  "男", "2505180205" };

	return 0;
}

打印结构体:

方法一:结构体对象.成员名

int main()
{
	//结构体的初始化
	struct Stu s = { "张三", 20,  "男", "2505180205" };

	//方法一:结构体对象.成员名
	printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);

	return 0;
}

方法二:结构体指针变量->成员名

void print(struct Stu* ps)
{
	printf("name = % s age = % d sex = % s id = % s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).id);

	printf("name = % s age = % d sex = % s id = % s\n", ps->name, ps->age, ps->sex, ps->id);
}


int main()
{
	//结构体的初始化
	struct Stu s = { "张三", 20,  "男", "2505180205" };

	方法二:结构体指针变量->成员名
	print(&s);

	return 0;

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/585021.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-12
下一篇 2022-04-12

发表评论

登录后才能评论

评论列表(0条)

保存