零基础玩转C语言系列第一章——初始C语言(下)

举报
安然无虞 发表于 2022/05/27 00:01:43 2022/05/27
【摘要】 目录 1、数组 1.1 数组定义 1.2 数组的下标 1.3 数组的使用 2、操作符 2.1 算术操作符 2.2 移位操作符 2.3 位操作符 2.4 赋值操作符 2.5 单目操作符 2.6 关系操作符 2.7 逻辑操作符 2.8 条件操作符 2.9 逗号表达式 3、常见关键字 3.1 关键字typede...

目录

1、数组

1.1 数组定义

1.2 数组的下标

1.3 数组的使用

2、操作符

2.1 算术操作符

2.2 移位操作符

2.3 位操作符

2.4 赋值操作符

2.5 单目操作符

2.6 关系操作符

2.7 逻辑操作符

2.8 条件操作符

2.9 逗号表达式

3、常见关键字

3.1 关键字typedef

3.2 关键字register

3.3 static关键字

1.static修饰局部变量

 2.static修饰全局变量

3.static修饰函数

4、#define定义常量和宏

5、指针

 6、结构体

7、结束语


【前言】:该篇博文是对初始C语言(上)的补充,内容不多,不过这部分有很多的知识点属于C语言中的重难点,所以小伙伴们好好康康哦。

【声明】:初始C语言部分就是简单介绍一下C语言的大体知识,所有知识点都是点到为止,后面博文中笔者会详细介绍。

在进入正文之前,麻烦铁汁们将初始C语言(上)再回顾一遍。

https://blog.csdn.net/weixin_57544072/article/details/120799064?utm_source=app&app_version=4.17.0

1、数组

要存储 1-10 的数字,怎么存储?
C 语言中给了 数组的定义:一组 相同类型 元素的集合

1.1 数组定义

//定义一个整型数组,并且给定了其大小,最多放10个元素
int array[10] = {1,2,3,4,5,6,7,8,9,10};

1.2 数组的下标

C 语言规定:数组的每个元素都有一个下标, 下标是从0开始的
数组可以通过下标来访问的
比如:
int array[10] = {1,2,3,4,5,6,7,8,9,10};
//该数组是10个元素,下标的范围是0-9

1.3 数组的使用

举个栗子:

#include<stdio.h>
int main()
{
	int i = 0;//使用i产生下标
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	while (i < 10)
	{
		printf("%d ", arr[i]);//通过下标来访问数组
		i++;
	}
	putchar('\n');
	return 0;
}

2、操作符

C语言中包含了非常丰富的操作符,所以有人说,C语言是非常灵活的。甚至可以直接对二进制位进行操作。

2.1 算术操作符

+   -   *   /   % 

这里先简单介绍一下特别容易出错的/ 和 % 

  • / : double ret = 7 / 2;   结果是3.000000(暂时先不用管为什么小数点后面那么多0),实际上我们想要的结果是3.5, 那该怎么办呢?改成double ret = 7.0 / 2; 或者改成double ret = 7 / 2.0;
  • %:取模,也叫求余,一定要注意的是取模操作符只能应用于整数哦,浮点数是不可以的,这点一定要注意。比如:7 % 2 = 1;(商3,余1)

2.2 移位操作符

>>   <<

为什么叫移位操作符呢?因为其作用于一个数的二进制位

左移:<< 相当于乘法

右移:>> 相当于除法

2.3 位操作符

&   ^   |

这里的“位” 指的是二进制位

按位与&:对应的二进制位有0,则为0,全1在为1;

按位或|:对应的二进制位有1,则为1,全0才为0;

按位异或^:对应的二进制位相同,则为0,相异才为1;

注意:对位操作实际上是对存储在内存上的二进制位进行操作的,然而整数在内存上存储的是其二进制的补码形式,所以对位操作,也就是对二进制的补码进行的操作。

2.4 赋值操作符

=   +=   -=   *=   /=   &=   ^=   !=   >>=   <<=

除了第一个,后面几个属于复合运算符

2.5 单目操作符

!                逻辑反操作
-                负值
+               正值
&               取地址
sizeof       操作数的类型长度(以字节为单位)
~               对一个数的二进制按位取反
--               前置、后置--
++             前置、后置++
*                间接访问操作符(解引用操作符)
(类型)       强制类型转换
单目操作符:操作数只有一个,什么叫操作数呢?比如:2 + 3 --> 2和3就是操作数,由于‘+’有两个操作数,数以叫双目运算符。
注意:sizeof计算的是类型或者是由类型定义的变量的大小,单位是字节。 C语言中用0表示假,非0表示真 ,注意是非0表示真,即使是-1也表示真,Do you understand?

2.6 关系操作符

>
>=
<
<=
!=       用于测试不相等
==      用于测试相等

2.7 逻辑操作符

&&   逻辑与---“并且”

||      逻辑或---“或者”

2.8 条件操作符

exp1 ? exp2 : exp3

注意exp代表的是表达式,后面还会提到。

条件运算符,又称为三目运算符,表达式1为真,则计算表达式2的值,跳过表达式3,也就是说表达式2的结果就是整个表达式的结果;反之,若表达式1为假,跳过表达式2,直接计算表达式3的值,也就是说表达式3的结果就是整个表达式的结果。

2.9 逗号表达式

exp1,exp2,exp3...expN

注意:逗号表达式会从左向右依次计算,整个表达式的结果是最后一个表达式的结果

3、常见关键字

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
注意:关键字先暂时简单介绍两个,后面会详细介绍
  • 关键字不能自己创建
  • 关键字不能作为变量名
  • define不是关键字

3.1 关键字typedef

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

比如:
typedef unsigned int uint_32;
//由于unsigned int比较复杂,所以用typedef将它重命名为uint_32,所以此时uint_32就是一个类型名,代表了unsigned int

3.2 关键字register

register---寄存器关键字 

 

register int a = 10; // a是寄存器变量

 register 是起到的是建议作用,“建议” 编译器将a放到寄存器中,不会真的放进去,它有自己的一套判断规则。

注意:不能对寄存器变量取地址,如上面的&a就是错误的

3.3 static关键字

static ---静态的

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

  • 修饰局部变量---静态局部变量
  • 修饰全局变量---静态全局变量
  • 修饰函数---静态函数

1.static修饰局部变量

//代码1
#include<stdio.h>
void test()
{
	int a = 1;//局部变量a的作用域在test()中,当a出了作用域就被销毁了,下次调用test()时,又需要重新创建a
	a++;
	printf("%d ", a);
}

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

 

//代码2
#include<stdio.h>
void test()
{
	//static修饰局部变量a
	static int a = 1;
	a++;
	printf("%d ",a);
}

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

                 

看:上面的两个代码几乎一样,只不过第二个代码中自定义函数test()里面用static修饰局部变量,所以出现了这样的差异。

根据代码2的结果推测出每一次调用test(),使用的a都是上一次函数调用时留下的a;第二次调用test()时,由于上次函数调用产生的a没有被销毁,所以不会再次创建a,直接跳到了下一步,a++

注意:static修饰局部变量的时候,其实是改变了变量的存储类型,由栈区存储变成了静态区存储,从而使得静态的局部变量出了自己的作用域也不会被销毁,其实也就是相当于改变了这个变量的生命周期。

这里补充一条小知识点:

内存是一块比较大的空间,在使用内存的时候,会划分出不同的功能区域:栈区、堆区、静态区

 2.static修饰全局变量

//代码1
//add.c文件
int g_val = 2018;//g_val是在add.c文件中定义的

//test.c文件
//如果想使用来自其他文件(外部文件)的全局变量,要先声明一下
extern int g_val;
//extern是一个关键字,专门用来声明外部符号的
int main()
{
	printf("%d\n", g_val);
	return 0;
}

 上面这个程序是正常编译的,不过下面的这个程序就不一定了哦

/代码2
//add.c文件
static int g_val = 2018;

//test.c文件
extern int g_val;

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

上面这个程序编译的时候会报错,因为出现连接性错误。

解释:一个全局变量在整个工程中的其他子文件内部能被使用,是因为全局变量具有外部链接属性 ,什么叫外部链接属性,一个变量在一个文件中定义,但是在另一个文件中可以使用(访问)叫外部链接属性。当一个全局变量被static修饰的时候。其外部链接属性就变成了内部连接属性;使得这个全局变量只能在只能在自己的源文件内部使用,其他文件不能再使用,因为它不再具有外部链接属性,给我们的感觉是作用域变小了。

另外,局部变量只有内部连接属性

3.static修饰函数

//代码1
//add.c文件
int Add(int x, int y)
{
	return x + y;
}

//test.c文件
extern int Add(int x, int y);
int main()
{
	printf("%d\n", Add(2, 3));
	return 0;
}

上面的程序编译正常,但是下面的程序编译时会出现错误哦。

//代码2
//add.c文件
static int Add(int x, int y)
{
	return x + y;
}

//test.c文件
extern int Add(int x, int y);
int main()
{
	printf("%d\n", Add(2, 3));
	return 0;
}

 这个程序编译时出现连接性错误。

因为函数也具有外部链接属性,static修饰函数的时候,函数本来是具有外部链接属性的,但是被static修饰后,就变成了内部连接属性,导致这个函数只能在自己的源文件内部使用,给我们的感觉是改变了作用域。

4、#define定义常量和宏

//define定义标识符常量
#define MAX 100

//define定义宏(宏和函数是非常相似的)
#define Add(x, y) ((x) + (y))

5、指针

指针这块内容是非常重要的,与此同时,指针也是很难的,不过铁汁们放心哦,后面笔者会用大量的篇幅去介绍它,这里,简单让大家了解一下。

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

#include<stdio.h>
int main()
{
	int num = 10;//num要在内存中开辟空间

	&num;// 取出num的地址,地址也称为指针,注意这里num是一个整型变量,4个字节,每个字节都有地址
	//但是取出的是第一个字节的地址(较小的地址)
	printf("%p\n", &num);//%p是以地址的形式进行打印

	int* p = &num;

	*p = 20;//p是用来存放地址的,p是一个指针变量

	return 0;
}

上面代码中的num 和 p 在内存中就像下图那样存储,只是一个抽象的图,现在看不懂没关系,因为这里只是简单了解,后面笔者会详细介绍的。 

 这里分析一段程序:

#include<stdio.h>
int main()
{
	int num = 10;

	int* p = &num;//int前面的‘*’告诉我们p是一个指针变量,这里的int表示p指向一个整型变量

	*p = 20;//‘*’是解引用操作符,通过p的值,我们找到了p所指向的对象,所以‘*p’就是‘num’


	return 0;
}

 计算指针变量的大小:

指针变量有多大?地址的存放需要多大空间?地址是如何产生的?地址是什么样的数据?

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

注意编译器上X86代表32位,X64代表64位

 

 6、结构体

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

人:复杂对象(名字 + 年龄 + 性别 + ...);

书:复杂对象(书名 + 作者 + 出版社 + ...)

.......

生活中还有很多这样的复杂对象

#include<stdio.h>
int main()
{
	struct Stu//结构体类型
	{
		char name[20];//名字
		int age;//年龄
		char sex[5];//性别
	};

	//结构体初始化
	struct Stu s = { "小高", 20, "未知" };

	//'.'为结构体成员访问操作符    用法:结构体变量 . 结构体成员
	printf("name = %s age = %d sex = %s\n", s.name, s.age, s.sex);

	//'->'操作符
	struct Stu* ps = &s;
	printf("name = %s age = %d sex = %s\n", (*ps).name, (*ps).age, (*ps).sex);
	printf("name = %s age = %d sex = %s\n", ps->name, ps->age, ps->sex);

	//注意'.'和'->'都是结构体成员访问操作符
	return 0;
}

 

 

 补充:一个汉字是占两个字节的哟

7、结束语

初始C语言部分到此就结束咯,下一篇博文将会介绍选择语句和循环语句,感觉有所收获的铁汁们给笔者来个三连吧,感谢喔。

文章来源: bit-runout.blog.csdn.net,作者:安然无虞,版权归原作者所有,如需转载,请联系作者。

原文链接:bit-runout.blog.csdn.net/article/details/121000424

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。