来自:中南林业科技大学软件协会学术部:谢添
⏲ 时间:2022 - 10 - 05
官网:https://www.csuftsap.cn/
✏️ 本章所有提供代码均已测试,读万卷书不如行万里路,一定要把代码都自己敲一遍并测试
一件事,你若不想做,你会?找出千万个理由去拒绝,你若想做,你会绞尽脑汁的去想办法,做与不做,不在于你行不行,而在于你要不要。
计算机编程语言
,广泛应用于底层开发
。良好的跨平台特性
,一个标准规格写出的C语言程序可以在许多电脑平台上进行编译。是一套非常完备的工具和服务,可帮助您为 Microsoft 平台和其他平台创建各种各样的应用程序。Visual Studio 还可将您所有的项目、团队和利益干系人联系在一起。现在您的团队可以从任何位置以虚拟方式进行更为敏捷的合作,无论他们采用何种开发工具。
可以通过强大的集成开发环境构建面向 Windows、Android、iOS 以及 Web 的出色应用。使用任何 IDE 或编辑器在云中进行版本控制、敏捷、持续交付、应用程序分析协作。
适用于所有操作系统的编辑器使用可在 Windows、OS X 或 Linux 上运行的免费代码编辑器构建和调试现代 Web 和云应用程序。
在学习C语言的过程中,编译环境和编辑器肯定是必不可少的。比如大家常见的VC 6.0
,Dev
,g++
等等,但是目前市场上使用最广泛,相对成熟的集成开发环境依旧是Visual Studio。
只是很多高校在教学实践中普遍采用VC或者Dev,因为文件小,安装便捷嘛!不过相对而言,这些软件对初学者往往不够友好,包括界面、提示符、文件系统等等。
而与之对应的,VS凭借它出色的界面、友好的操作方式和完备的体系得到很多开发者的青睐,所以也是奉劝一些仍在坚持学校的软件的学弟学妹入坑VS,只有四个字送给你们:绝对不亏!
必学必会
VS官网:https://visualstudio.microsoft.com/zh-hans/vs/
推荐视频教程:https://www.bilibili.com/video/BV11R4y1s7jz/?spm_id_from=333.337.search-card.all.click
Hello World是一个最著名的程序。对每一位程序员来说,这个程序几乎是每一门编程语言中的第一个示例程序。实际上,这个程序的功能只是告知计算机显示Hello World这句话。传统意义上,程序员一般用这个程序测试一种新的系统或编程语言。对程序员来说,看到这两个单词显示在电脑屏幕上,往往表示他们的代码已经能够编译、装载以及正常运行了,这个输出结果就是为了证明这一点。这个测试程序在一定程度上具有特殊的象征意义。在过去的几十年间,这个程序已经渐渐地演化成为了一个久负盛名的传统。几乎所有的程序员,无论是在你之前,或在你之后,当第一次实现与计算机成功沟通之后,在某种程度上,他们的肾上腺素就会急剧上升(激动不已)。
#include
int main() {
printf("Hello World:你好,软件协会");
return 0;
}
一个C程序就是由若干头文件和函数组成。
预处理
命令, 它的作用是通知C语言编译系统在对C程序进行正式编译之前需做一些预处理工作。一个C程序有且只有一个主函数,即main函数。
int
就是主函数的返回值类型
。printf()
是格式输出函数
,这里就记住它的功能就是在屏幕上输出指定的信息\n
是转义字符中的换行
符。Tab
键为一个缩进。括号要成对写
,如果需要删除的话也要成对删除。一句可执行语句结束
的时候末尾
需要有分号
。英文半角符号
。针对不同的数据,采取不同的存储方式和进行不同的处理。随着处理对象的复杂化,数据类型也要变得更丰富。数据类型的丰富程度直接反映了程序设计语言处理数据的能力。
C语言很重要的一个特点是它的数据类型十分丰富。因此,C语言程序数据处理功能很强。C语言丰富的数据类型可归纳如下:
我们现在要讲的呢,只是对数据类型的简单了解,我们后面的章节再详细讲解各种数据类型。当然,关于基本数据类型还有很多值得探究的地方,也会放在后面补充,毕竟一口气吃不了那么多,就像你能一下子追到你的男神或女神 吗?肯定是要有个循序渐进,循循善诱的过程嘛
类型 | 说明 |
---|---|
short / short int | 短整型 |
int | 整型 |
long | 长整型 |
long long int | 更长的整型 |
float | 单精度浮点型 |
double | 双精度浮点型 |
char | 字符数据类型 |
C语言没有字符串类型
哦,但是我们可以使用字符数组
,或者用指针指向字符串,现在不理解没关系,我们先在这稍微提一嘴
以上类型都有两种子类型:有符号数(signed XXX)
、无符号数(unsigned XXX)
。二者最大的区别:表示的值的范围大小不同,signed > unsigned。
在讲这个前,我们先来简单聊聊字节:
计算机最小的存储单位: bit
比特位。一个比特位存放一个二进制数字 0
/ 1
。
再大一点的单位是 byte
字节。一个字币=8个比特位。
它们之间的换算规则是这样的:
那字节大小如何确定取值范围的呢?
一个字节 = 8 bit
1 bit 可以存放 0 或 1
那么 1 bit 可以表示两个数:0 1
那么 2 bit 可以表示 2 * 2 即 4 个数:00 01 10 11 分别代表0,1,2,3
这样算下来,8 bit 可以存放2的8次方即256个数
那unsigned short类型占2字节,一共16 bit,不就可以表示65536个数吗
从 0 ~ 65536 不就是65535个数吗
这里其实还涉及到进制,如果你想了解进制,可以在软协官网下载资源《进制,原码反码补码,位运算》,帮你打通进制从而理解取值范围
也可以查看链接(CSDN上发表):https://blog.csdn.net/qq_62982856/article/details/126052638?spm=1001.2014.3001.5501
数据类型 | 字节大小 | 取值范围 |
---|---|---|
short | 2字节 | -32768~32767 |
unsigned short | 2字节 | 0~65535 |
int | 4字节 | -2147483648~2147483647 |
unsigned int | 4字节 | 0~4294967295 |
long | 4字节 | -2147483648~2147483647 |
unsigned long | 4字节 | 0~4294967295 |
long long | 8字节 | 9,223,372,036,854,775,808~9,223,372,036,854,775,807 |
unsigned long long | 8字节 | 0~18,446,744,073,709,551,616 |
float | 4字节 | -3.4*10^38~3.4*10^38 |
double | 8字节 | -1.7*10^308~1.7*10^308 |
long double | 8字节 | -1.7*10^308~1.7*10^308 |
unsigned 是无符号的意思,我们以 short 和 short int 来说明,short 就是有符号数,unsigned short 是 无符号数,但它们占的字节是相同的,则能表示的数的个数也是一致的,short 从 -32768~32767 一共 65536 个整数,unsigned 从 0 ~ 65535 不也是 65536 个整数吗
计算字节大小,我们可以使用 sizeof(数据类型)
这个单目运算符
(sizeof(数据类型)不是函数哦,C/C++语言编译器在预编译阶段的时候就已经处理完了sizeof的问题,也就是说sizeof类似于宏定义),它的返回值是括号内的数据类型的字节大小,在这里先简单使用一下,后面章节会详讲。不多说,上代码。
#include
int main()
{
//sizeof:计算()内数据所占内存空间大小,单位是字节。
printf("char = %d\n", sizeof(char)); //计算字符型字节大小
printf("short = %d\n", sizeof(short)); //计算短整型
printf("int = %d\n", sizeof(int)); //计算整型
printf("long = %d\n", sizeof(long)); //计算长整型
printf("long long = %d\n", sizeof(long long)); //计算更长整型
printf("float = %d\n", sizeof(float)); //计算单精度浮点型
printf("double = %d\n", sizeof(double)); //计算双精度浮点型
return 0;
}
运行来看看结果吧:
❗️ 提一个问题:
问题出在sizeof
上,它返回的是一个64位 (8 bytes
)的无符号整型
再看看我们使用的占位符 %d
,在格式化输入输出中代表int(4bytes
),%ld
代表long int(>=4bytes
), %lld
代表long long int (8 bytes
);
那你应该很清楚应该怎么改才能消除警告了吧, 修改后的代码
#include
int main()
{
//sizeof:计算()内数据所占内存空间大小,单位是字节。
//将 %d 修改为 %lld
printf("char = %lld\n", sizeof(char)); //计算字符型字节大小
printf("short = %lld\n", sizeof(short)); //计算短整型
printf("int = %lld\n", sizeof(int)); //计算整型
printf("long = %lld\n", sizeof(long)); //计算长整型
printf("long long = %lld\n", sizeof(long long)); //计算更长整型
printf("float = %lld\n", sizeof(float)); //计算单精度浮点型
printf("double = %lld\n", sizeof(double)); //计算双精度浮点型
return 0;
}
我们以 short 类型为例,在 4.2
提到它的取值范围为 -32768~32767 ,那就说明最大值是 32767,不能取 32768
上代码测试:
#include
int main()
{
short temp1 = 32767;
short temp2 = 32768;
printf("temp1 = %d\n", temp1);
printf("temp2 = %d\n", temp2);
}
看下输出结果吧,可以看到temp2的值是超过了 short
的取值范围,因此输出temp2显示的不是我们定义的32768,而是负值
至于为什么是负值,这里不详说,涉及到底层的二进制运算,以后有机会单独拉出来解释。
生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型,张若昀对唐艺昕的爱)
有些值是可变的(比如:年龄,体重,薪资,渣男的爱)。
不变的值,C语言中用常量
的概念来表示,变得值C语言中用变量
来表示。
int age = 150;
double weight = 45.5;
char ch = 'w';
//我们也可以进行修改
age = 520;
weight = 13.14;
1️⃣ 局部变量
内部变量
。局部变量是在函数内作定义说明的。其作用域仅限于函数内.离开该函数后再使用这种变量是非法的。平行关系
。2️⃣ 全局变量
全局变量也称为外部变量
,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件,其作用域是整个源程序。
3️⃣ 注意事项
如果同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量被“屏蔽”,即它不起作用。这就是我们以后会常提起的**就近原则**
#include
int global = 2022;//全局变量,定义在main函数外部
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}
这是不会有问题的,是允许全局变量与局部变量同名的,但如果在main函数中显示,显示的是2022还是2020呢?
根据就近原则
,printf(“global = %d\n”, global);也在main函数当中,说明局部的变量
离这条语句更近,因此显示的是 2020
1️⃣ 作用域
作用域(scope)
是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
2️⃣ 生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
现在你或许还不是很太理解,毕竟第一次接触,但等我们讲到函数还会继续讨论变量的作用域和生命周期。❤️
C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:
这里我们先提 字面常量
与 const修饰的常变量
,后面两个以后再说。
100;//字面常量
2.5;//字面常量
1;//字面常量
#include
int main()
{
//这个 100 就是字面常量,而a是变量
//我们相当于是把 字面常量100 赋值给了 变量a
int a = 100;
//我们可以对 变量a 进行修改
//变量a 原来的值是 100 ,现在我们 将字面常量 520 赋值给了 变量a
a = 520;
return 0;
}
#include
int main()
{
const int num = 10;
printf("%d\n", num);
num = 20;
printf("%d\n", num);
return 0;
}
const — 常属性。num:const修饰的常变量,本质上,num还是一个变量。
可以看到,我们刚才写的代码是编译不通过的,可我们刚才又提到了 num 本质是变量,变量不是可以修改吗?这是咋了
其实,这个错误是在程序编译
的时候给出的,注意这里,这个时候并没有生成可执行文件,说明const修饰的变量可否修改是由编译器来帮我们保护了,编译器认为你既然声明了const
,那就不能给 const修饰的变量a 赋值。
但是,我们可以在可执行程序执行的时候对 const修饰的常变量a 进行修改,既然能修改,那 a 依旧还是个变量,因此 常变量本质还是变量 这句话是没错的,我们可以在 可执行程序执行的时候对常变量的值进行修改。
补充:
关于可执行程序执行时候与如何在此期间对常变量进行修改,等我们讲到指针再来细品。
这时候,你可能就有疑惑了,既然const修饰的常变量是可以修改的,那为什么我们有时候还是需要定义呢,干嘛不直接定义为普通变量呢,这样修改起来也多方便呀。
其实,const修饰的变量,其实质是告诉程序员或编译器该变量为只读,如果程序员在程序中显示的修改一个只读变量,编译器会毫不留情的给出一个error。因此程序员如果定义了一个 const修饰的变量,就是在告诉自己,或者其它阅读与继续编写你的代码的程序员,不要打主意去用指针修改我定义的这个const常变量,其它程序员看到你写的const常变量就会明白:“哦,这个常变量是有用的,我不要去改它,写这个const来修饰变量的程序员在告诉我不要去动它的值!”
#include
#define MAX 100 //设置 常量MAX 的值为 100
int main()
{
//将常量MAX的值赋值给 num
int num = MAX;
printf("%d\n", num);
return 0;
}
生活中有一些事物是可以列举的:星期、颜色、性别、月份等等。
枚举常量关键字:enum
#include
enum week //星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum girl{
Baby,
Judy,
Weddy
}
int main()
{
enum week day = Mon;
//从 枚举类型 girl 中挑选出 Weddy
enum girl myGril = Weddy;
return 0;
}
用最少单词表达出最详细的信息
原则。C 是一种简洁的语言, 命名也应该是简洁的。例如变量名MaxVal 就比MaxValueUntilOverflow 好用。标识符的长度一般不要过长。StudentAge
、StudentFatherName
这里说的是C语言的命名规范,但在其他语言比如Java语言中又会有所不同,这里提一嘴,希望注意。
"hello world"
"你好,软件协会"
"" //这是一个空字符串
这种由双引号(double quote — ""
)引起来的一串字符称为字符串字面值
(String Literal),简称字符串。
字符串的结束标志是一个\0
的转义字符。在计算字符串长度(strlen
)时, \0 是结束标志,不是字符串内容。。\0 对字符串来说,很重要。
这里呢也是稍微提一嘴,关于字符串我们放在数组细品。
还是上个代码,留个印象
#include
#include
int main()
{
char arr1[] = "jing";
printf("arr1 = %s\n", arr1);
printf("\n");
printf("arr1_length = %d\n", strlen(arr1));
return 0;
}
//strlen函数:计算字符串长度,遇到'\0'停止。
先上个例子引出转义字符(说明:\n代表换行符,即在输出时遇到了 \n 则会自动换行输出)
#include
int main()
{
printf("\now I love you");
return 0;
}
【什么是转义字符】
转义字符(Escape character),所有的ASCII码都可以用“\”加数字(一般是8进制数字)来表示。而C中定义了一些字母前加""来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。简单来说就是在一些字符前加 “\” 使它具有其他意义。
【常见的转义字符】
【水平制表符 \t 演示】
#include
int main()
{
printf("\tnow I love you");
return 0;
}
【面试题】
请说出下列代码的输入结果。
#include
#include
int main()
{
printf("%d\n",strlen("C:\test\32\code\test.c"));
return 0;
}
转义字符虽然包含两个或多个字符,但它只代表一个字符。编译系统在见到字符“\”时,会接着找它后面的字符,把它处理成一个字符,在内存中只占一个字节。
结果解释:
\
与其后面的(紫色)字符合起来算一个字符,4个。\
不计算长度。\32
解释:
1️⃣ 单行注释
#include
int main()
{
//这是一个单行注释
return 0;
}
2️⃣ 单行注释
#include
int main()
{
/*
这是一个多行注释
诶,你看,我可以写多行诶
*/
return 0;
}
多行注释即在/* */
内的内容都是注释
注释不能嵌套使用
#include
int main()
{
/*
我的外层注释
/*我的内层注释 */
*/
return 0;
}
上述代码是错误,这是为什么呢?
你想一个 /*
对应一个 */
,那我们从第一个 /*
开始看,往后走,遇到的第一个 */
只不是就是紧跟在我的内存注释
后面的那个*/
。因此在这里会直接进行匹配,至于最后一个 */
该何去何从呢?编译器给你报错呗!
看看就行,这些会在以后逐个讲到
//类型名
short int long char float double void
//选择、循坏
if else for switch break continue case default do while goto return
//自定义类型
struct union typedef enum
//修饰
const static extern auto signed unsigned
//其他
volatile sizeof register
C语言的输入输出其实很庞大,因为初学,我们先做简单了解,之后单独搞一个专门篇章(由入门到进阶)讲解。
话不多说,上代码进行用法说明:
#include
int main()
{
printf("软件协会欢迎你\n"); // \n是换行符,你可以试试不加换行的效果
int a = 10;
/*
%d 是int类型的占位符
逗号“,”后面的变量或变量就会去代替占位符,输出该变量的值
*/
printf("%d\n", a);
int b = 89;
printf("%d 有 %d ,%d 不离 %d\n", a, b, b, a);//这个结果你能想到吗
//刚才提到了也可以用常量,%lf 是double类型的占位符
printf("%lf", 13.14);
return 0;
}
运行结果:
这里也是先了解简单使用,目前使用你按下述模板来就行:
#include
int main()
{
//变量未定义值
int score;
printf("请给这篇文章打分(整数):");
/*
这个 %d 是占位符,在逗号“,”后面的是 &变量名
表示通过键盘给这个变量赋一个值
*/
scanf("%d", &score);
//我们输出,验证一下是不是我们通过键盘输入的值
printf("您给的分值是:%d", score);
return 0;
}
这个代码放在 dev
等编译器中是生效的,但在 VS
当中会报错,给出不安全警告,这是为什么呢?
由于微软工作人员从函数安全性
的考虑,在VS中弃用了scanf函数,之后创建了scanf_s函数来代替使用,所以在VS中,大多数时候我们还是使用scanf_s函数
所以我们只需在 VS 中对上述代码进行小小修改:scanf
统一改为 scanf_s
#include
int main()
{
//变量未定义值
int score;
printf("请给这篇文章打分(整数):");
/*
这个 %d 是占位符,在逗号“,”后面的是 &变量名
表示通过键盘给这个变量赋一个值
*/
scanf_s("%d", &score);
//我们输出,验证一下是不是我们通过键盘输入的值
printf("您给的分值是:%d", score);
return 0;
}
其实不是说不可以使用scanf函数,只不过是预处理器会发出错误警告并停止编译,如果想要坚持使用scanf函数的话,可以在头文件定义#define _CRT_SECURE_NO_WARNINGS
我们把上面的代码修改一下,依旧在 vs 中采用 scanf,上代码演示:
#define _CRT_SECURE_NO_WARNINGS //放在首行,在#include之前
#include
int main()
{
//变量未定义值
int score;
printf("请给这篇文章打分(整数):");
/*
这个 %d 是占位符,在逗号“,”后面的是 &变量名
表示通过键盘给这个变量赋一个值
*/
scanf("%d", &score);
//我们输出,验证一下是不是我们通过键盘输入的值
printf("您给的分值是:%d", score);
return 0;
}
本章我们初步了解了C语言以及基本的使用,遇到任何疑惑联系软件协会
了解更多关注软协官网:https://www.csuftsap.cn/
来自软件协会的编辑,注册会员可在官网下载所有开源.md
资源分享,请勿外传。