【全网最强C语言学习】C语言入门篇(主线)——初始C语言②

✨前言✨ 

        作为一个小白说出标题这样的话看来是有些大言不惭,但博主有心将这个系列做好、做精。实话说博主学习C语言不过两个多月,也很能明白初学者的困惑,所以会尽肯能详细。同时作为一个系统的教程,这个系列会持续推新的,所以关注博主🍻,在学习C语言的路上结伴前行吧!

🐱‍💻作者概况:  就读南京邮电大学努力学习的大一小伙

🐱‍🐉联系方式:2879377052(QQ小号)             [有问题欢迎留言讨论,作者尽力帮忙]✨

🐱‍👤资源推荐:C语言从入门到进阶

🐱‍🚀今日书籍分享:《C陷阱与缺陷》                   提取码:CSDN

🐱‍👓gitee码云链接: Gitee仓库 test


✨复习✨

        在上一篇博客里(没看过?点这里),我们学习了如何安装VS,并写下了第一段代码。重点知识如下,我以问题的形式帮助大家回想:

①main函数的作用?—— main函数的特点?

②什么是库函数?—— printf的各种格式控制符的作用?(慢慢熟悉,先记常用的)

库函数不会用,送你一本库函数字典

③什么是数据类型?—— 数据类型有哪些?—— 各种类型大小? —— 数据类型存在的意义?

④能否实现在屏幕上打印“hello world!” 

上面的问题都能回想起来说明上一篇文章掌握的很好。没掌握也没关系,再看一遍肯定会掌握的。好了,现在开始我们今天的学习内容。


目录

一、变量⭐

知识点一:什么是变量🌵

知识点二:如何使用变量🌕

知识点三:变量的分类🌕

 二、常量⭐

知识点一:什么是常量🌵

知识点二:有哪些类型的常量🌕

①字面常量🌲

②常变量:const🌳

③#define定义变量🌴

④枚举常量🌾

三、字符串⭐⭐

知识点一:字符串怎么存🌵

知识点二:\0是什么?有什么用 ?⭐⭐⭐

四、转义字符⭐

知识点一:什么是转移字符🌵

笔试题⭐⭐

五、后记(投个票再走呗)


一、变量⭐

知识点一:什么是变量🌵

顾名思义,变量就是可变的量,可以被任意的赋值和修改。与之相对的是常量,一旦被初始化之后便不可以被修改(后文会详细讲)

知识点二:如何使用变量🌕

变量的使用要遵循“先定义后使用的原则”。那什么是定义变量呢?定义变量就是创建一个对象,并根据变量的类型向内存申请相应大小的空间(如一个变量为int类型,则向内存申请4字节的空间)。我们现在创建了一个变量m,并给他初始化为10。

int main()
{
	int m = 10;
}

问题一:如果不初始化会怎么样?🤔

答:如果这个变量为全局变量,则其初始值为0。如果这个变量为局部变量,则其初始值为随机值(全局变量后文讲)。既然是随机值鬼知道他到底是多大(不看监控的话),所以在使用局部变量的时候要记得赋值,最好定义后随即跟上赋值,防止忘记赋值了。

 强行使用编译器也不会允许的

 易错一:分号

注意:新手在写代码的时候;老是会落掉。好在VS的报错够智能会即使提醒你。那有人会问分号有什么用呢?在c语言中一行表示一条语句,加上;表示这条语句的结束。

 补充一:C99之前的标准📜

在C99标准之前要求先变量定义要放在最前面。什么意思呢,现在演示一下。在C99标准下第二种写法就不正确了。但这个问题大家不用太关心,VS2013~VS2019对C99是支持的,所以以下都可以。

int main()
{
	int a=1;
	int b=1;
	b = a + 1;
	return 0;
}

int main()
{
	int a = 1;
	int b = a + 1;
	return 0;
}

 知识点三:变量的分类🌕

变量分为全局变量和局部变量。怎么区分的呢?其实很简单,在代码块外的就是全局变量,在代码块内的就是局部变量。(代码块就是“{ }”)

(里面的for语句先别管,以后会提到) 

int g_val = 1;//全局变量
int main()
{
	int i=1;//局部变量
	int count = 0;//局部变量
	for (i = 1; i < 3; i++)
	{
		int j = 1;//局部变量
		for (j = 1; j < 3; j++)
		{
			count++;
		}
	}
	return 0;
}

 建议一:全局变量

在C程序里最好少用全局变量。试想一个几万行代码的工程突然冒出来一个变量不免让人疑惑。如果一定要使用全局变量,在命名时最好加上g_,g就表示global嘛,表明它是一个全局变量,避免人们误会。

 问题一:全局变量和局部变量的区别 

区别一

谈到两者的区别不得不提到两个概念:作用域和生命周期

作用域:就是变量有效的范围。局部变量的作用域在它所在的代码块范围内

……{   { int i {  { …… } } }  }如这里i在随后的两个代码块里都是可以用的,但是在最外面的代码块已经出了它的作用域。

全局变量的作用域是整个工程,即在一个工程文件下即使在多个.c文件内都可以使用。

生命周期:变量的创建到变量的销毁之间的一个时间段

就如上文所提到的i,{ int i }进入代码块i被创建,出代码块i被销毁

生命周期和作用域在表现效果的时候有重叠的现象,但一个是空间一个是时间。不理解也没必要深究

在上文作用域和生命周期的介绍中已经体现全局部变量的区别,现在看实际代码加深理解

全局变量跨文件使用只要声明一下就可以了 

顺便谈谈声明与定义的区别:声明的关键字extern

定义就好比两个人确定男女朋友关系,只能定义一次,总不能两个人好着但又确定男女朋友关系吧🤔。所以代码里不能出现两次的   int  xxx=xxx;

声明就好比你高兴的和室友说你有女朋友了,只要室友不打死你,你说多少次都可以,可以多次声明🤣

区别二:全局变量开辟在内存上的静态区;局部变量开辟在内存上的栈区。(不深究,以后会讲)

问题二: 全局变量和局部变量重名问题

        大家看以下这段代码,判断输出结果

#include<stdio.h>
int g_val=10;
int main()
{
    int g_val=100;
    printf("%d\n",g_val);
    return 0;
}

当全局变量和局部变量重名时,遵循“局部变量优先”原则。所以打印的结果为100 


 二、常量⭐

知识点一:什么是常量🌵

顾名思义,常量就是固定不变的量,一旦被初始化后便不可以被修改。

 问题一:以下行为算是修改吗?(const 修饰表示这个数为常变量)

int main()
{
	const int a = 10;
	return 0;
}

 答:初始化不算修改。初始化之后便不可以被修改,不信去试试。

知识点二:有哪些类型的常量🌕

①字面常量🌲

很简单,就是如10,20,‘a’,‘b’;

②常变量:const🌳

const为关键字,说明这个类型的数据为“只读变量”。被const修饰的变量具有某种常属性——即只可以被读取,但是不可以被修改。然而他本质上还是个变量,只不过具有常属性。我们以下面的例子说明。

上面有我们没提到的数组,也顺便讲一下吧。其实很简单,数组就像一个连续货架,他们在内存上开辟的空间连续。这里的int表示数组存储的数据类型为int ,【】表示这个数组有多大,这里为10,说明可以存放十个整形。整形的赋值要用{},赋值为{0}表示将数组里十个元素都赋值为0。这里不细讲,可以看看别人的博文     点这里前往——数组

这里想表达的是,【】内必须是一个常量,而a即使别const定义了还是不能用,说明他本质还是变量

补充一: 

在C99语法中支持变长数组这一概念,即【】内可以是变量。但在VS2019 c语言中不支持,且这种方式也不大流行。如果你【】内放入的是变量但是却没有报错,看看自己文件后缀是.c还是.cpp,cpp表示的是c++文件,在c++中是允许的,这点在主线①中有指出过。

③#define定义变量🌴

define定义的就是一个真常量了 ,不行你看 ,以下代码没有任何问题。博主的注释也可以看看,刚写也掉进坑了

#define MAX 10 //没有“=”注意! ,没有;
int main()
{
	int arr1[10] = { 0 };
	int arr2[MAX] = {0};
	return 0;
}

建议一:

#define定义的变量最好名字为大写 

 ④枚举常量🌾

有些事物是可以一一列举的比如性别,我们可以创建一个枚举变量,使用的时候引用就行。

注意中间使用逗号分隔的,不是分号

int main()
{
	enum SEX   //创建枚举常量
	{
		MALE,
		FEMALE,
		SECRET
	};
	enum SEX man = MALE;//使用枚举常量创建变量
	return 0;
}

创建的变量都是有值得我们可以打印一下

 这个值也是可以改变的,但他们还是按顺序增长的


三、字符串⭐⭐

知识点一:字符串怎么存🌵

我们学过字符类型,那该怎么储存字符串类型呢?是不是在C语言里也有字符串对应的类型吗。我只能遗憾的告诉你,在C语言里并没有字符串类型,那我们该怎么存放字符串呢?

字符串储存在数组中,用“”引起来(注意区别:字符是用''引起来的)。我们现在演示一下

int main()
{
	char str[] = "abcd";//数组不指定元素个数则根据后面元素的个数确定
	return 0;
}

我们从上面可可以看到字符串的本质是一个数组,里面一次存入各个字符

‘a’    ‘b’    ‘c’    ‘d’    ‘\0’

\0是什么?明明没有啊。别急,你现在只需记住,凡是字符串在末尾都会自带一个\0

知识点二:\0是什么?有什么用 ?⭐⭐⭐

是什么:\0的ASCLL码值为10,他标志着字符串的结束。

有什么用:就如是什么中提到的,他标志着字符串的结束。没有\0就无法判断一个字符串是否结束。比如strlen和printf以%s的格式打印时就是一直运行直到到达\0停止

我们现在用sizeof和函数strlen(库函数,作用是返回一个字符串的长度。尝试用博主上文提到的方法自主学习,不会欢迎向作者提问) 来验证\0的存在

 size为什么会比strlen长呢?这从侧面说明了\0的存在,要额外占用一字节的空间,而strlen本质上是计算出\0前的字符数。

什么你还不信,那就给你看看内存里到底存的是什么。首先要ctrl+fn+f10(或者ctrl+f10)进入调试状态,敲黑板,一定要进调试状态,不然看不到。 

 怎么样,信了吧。

那来看看一下的几个问题:

问题一:下面打印的结果是

#include <string.h>//库函数要引用头文件
#include <stdio.h>
int main()
{
	char str[6] = "abcdef";
	printf("%s",str);

	return 0;
}

 这是什么鬼东西?别急我们仔细观察下,我们在创建数组是指定了数组的长度为6,也就是说\0放不进去了,所以打印字符串就不知道什么时候会停下来,直到它幸运的在后面遇到一个\0,因此会多很多奇怪的东西。

问题二:下面打印的结果是什么

#include <string.h>//库函数要引用头文件
#include <stdio.h>
int main()
{
	char str[] = {'a','b','c','d','e','f'};
	printf("%s", str);

	return 0;
}

 这又是什么鬼结果?明明字符串大小已经可以自动调节了,可结果怎么还是这么奇怪。来我们分析一下。我们将六个字符存入字符串,这时\0没有被加入,为什么?因为你没写啊。而“abcdef”里的\0是字符串类型自带的,可这里只是把字符放进去,怎么改呢?既然不自动加\0我们就自己加嘛!

​ 问题三:下面打印的结果是什么

#include <string.h>//库函数要引用头文件
#include <stdio.h>
int main()
{
	char str[7] = {'a','b','c','d','e','f'};
	printf("%s", str);

	return 0;
}

 咦,为什么这样就可以了。因为字符类型的数组,空间有多,自动存入\0。现在我们验证一下


四、转义字符⭐

知识点一:什么是转移字符🌵

我们现在猜测一下下面的结果是什么

#include<stdio.h>
int main()
{
	printf("c:\test\test.c");
	return 0;
}

来揭晓答案

 为什么会这样呢?其实就是转义字符在作怪。那到底什么是转义字符

是什么:'\'+某个特定字符表示特定的意思(注意转义字符是C语言规定的,不能自行设置)。我们之前就见过\n,他表示换行符。

转义字符

意义

ASCII码值(十进制)

\a

响铃(BEL)

007

\b

退格(BS) ,将当前位置移到前一列

008

\f

换页(FF),将当前位置移到下页开头

012

\n

换行(LF) ,将当前位置移到下一行开头

010

\r

回车(CR) ,将当前位置移到本行开头

013

\t

水平制表(HT) (跳到下一个TAB位置)

009

\v

垂直制表(VT)

011

\\

代表一个反斜线字符''\'

092

\'

代表一个单引号(撇号)字符

039

\"

代表一个双引号字符

034

\?

代表一个问号

063

\0

空字符(NUL)

000

\ddd

1到3位八进制数所代表的任意字符

三位八进制

\xhh

十六进制所代表的任意字符

十六进制

 现在我们来演示一下。结果大家实际操作一下。

#include<stdio.h>
int main()
{
	printf("abc\b\n");//b相当于backspace
	printf("abc\rd\n");//r相当于用鼠标将光标移到开始位置,也就是a,此时我们在这里输入d
	printf("abc\tdef\n");//t相当于table,水平制表符
	printf("\\n\n");//就是想要输出\n而不要理解成换行符,就把\给转义
	printf("\"\n");//不加\,则第一个“会和第二个”自动组合,第三就会显示不匹配的问题
	printf("\110\n");//1到3个小于8的数字,理解为八进制数字。对照ASCLL码表转化为字符输出
	printf("\x61\n");//x加上任意个小于16的数字表示16进制

}

笔试题⭐⭐

#include<stdio.h>
int main()
{
	printf("%d\n", strlen("c:\test\628\test.c"));
	return 0;
}

答案:14

分析:1.一个转义字符虽然由多个符号组成,但计算字符个数时,当成一个

            2.\628虽然有三个数字,但8不可能是8进制的数字,所以自动忽略

              再比如\6687则这里的转义字符为\66,后面不算

c  :\t  e  s  t  \62  8  \t  e  s  t  .  c                              一共14个    

五、后记

        一不小心写了6000+,是不是我太啰嗦了🤣 。但不管怎么样还是希望对大家有帮助吧。再给大家提个小建议,遇到不会或是什么bug,百度和CSDN都是很好平台去寻求解决方案,也提升自己个人解决问题能力。写的代码可以保存到代码仓库(不会上传,看这里),小绿点是你努力的证明。

主线③已更新:主线③

没看过瘾,看看新推出的《深入剖析系列》         —— ——         《深入剖析C语言》C语言与内存

  • 115
    点赞
  • 149
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 38
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罅隙`

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值