各位观众老爷!啊不,各位小伙伴你们好啊,欢迎来到C语言系列文章之初识C语言的学习,今天我将带领各位小伙伴一起,进入C语言的世界,对C语言的学习有一个宏观上的认识。那话不多说,我们开始吧。
什么是C语言呢?它是20世纪70年代初期在贝尔实验室开发出来的一种广为使用的编程语言。显然,这一简单回答并没能传达出C语言的特别之处。不过别急,在深入学习这门语言之前,让我们先简单回顾一下C语言的起源。
C语言起初诞生于贝尔实验室,是当时为开发UNIX系统所设计出的的“副产品”。其实C语言的发展最早可以追溯到Algol60语言,也就是我们所说的A语言,后来随着时间的推移,Thompson想要使用一种更加高级的的编程语言来完成UNIX系统的开发,于是他设计了一种小型的B语言;随着计算机的不断发展,同实验室的Ritchie开始着手升级B语言,并命名为NB语言;但后来,由于新语言逐渐偏离B语言,于是更名为C语言。
C语言的标准化,从一开始的K&R白皮书(1978年编写的一本C语言必读圣经),到后来美国ANSI于1989/1990年制定的C语言标准,简称C89/C90。后续陆续也制定了C99,以及最近的C11标准等。
想必大家除了C语言还听说过别的编程语言,不过现代的编程语言大多都借鉴了C语言的特性,正所谓C生万物。像我们熟知的C++,JAVA,C#等,区别也有很多,比如C语言是面向过程的语言,C++,JAVA等是面向对象的语言,这些语言我们后期可以选择自己感兴趣的进行更加学习,不过在这之前,学好C语言这一基础对于我们后续的学习十分重要。
这些东西大家了解一下就可以啦,感兴趣可以自己call度娘。
代码如下:
#include
//引入头文件
int main(){
//定义返回值为int类型的main主函数,一个工程中main函数有且仅有一个
printf("大家好!我是练习时长两年半的个人偶像练习生:\n");
printf("蔡徐坤!\n");
printf("喜欢唱,跳,RAP!\n");
//C语言中的库函数printf,用来输出一段内容,\n为换行符,进行换行。
return 0;
//返回0给系统,
}
运行结果如下:
大家好!我是练习时长两年半的个人偶像练习生:
蔡徐坤!
喜欢唱,跳,RAP!
这样,我们就完成了一个简单的C语言程序的编写!是不是很简单!
计算机在处理数据的时候是处理二进制的数据,如010111111001,C语言中有很多数据,这些数据也有很多不同的类型,这样可以方便我们处理各种生活中不同的东西。
下面让我们了解一下C语言基本的数据类型
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
测试代码如下:
#include
int main() {
printf("%d\n",sizeof(char)); //1 byte
printf("%d\n",sizeof(short)); //2 byte
printf("%d\n",sizeof(int)); //4 byte
printf("%d\n",sizeof(long)); //4 byte
printf("%d\n",sizeof(long long)); //8 byte
printf("%d\n",sizeof(float)); //4 byte
printf("%d\n",sizeof(double)); //8 byte
return 0;
}
运行结果如下:
1
2
4
4
8
4
8
需要注意的是,在这里我是用的是vs2022的编译器,在32位和64位的环境下结果一样,在其他编译器上也会出现long的大小是8个字节的情况,所以具体还得看编译器。
生活中有许多值,有些事可变的,有些是不变的
比如你的身高,体重,年龄是可变的,在C语言中叫做变量
又如你的血型,性别,身份证号码是不变的,在C语言中叫做常量
#include
int main() {
int age = 18;//定义整型的年龄
char sex = 'M';//定义字符类型的性别
float salary = 1600.0f;//定义浮点类型的工资
printf("年龄=%d ,性别=%c,工资=%f",age,sex,salary);
return 0;
}
1.只能由字母、数字、下划线组成,如a,_a5
2.不能由数字开头,如89w非法
3.区分大小写,如age和AGE是两个不同的变量
4.不能用关键字命名,如int int=0;非法
5.长度不能超过63个字符(尽量不要太长)
一个题外话,我想测试一下变量名究竟有多长,于是我打开我的vs2022,开始int aaa………………测试了一下,结果长度是4096个字符,再多一个就报错啦,爆出标识符超过用于标识符的内部缓冲区的长度的错误。
全局变量和局部变量
#include
int global = 2022;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("global = %d\n", global);
return 0;
}
运行上述代码,代码运行正常,结果显示 global = 2020;
这证明了global虽然定义了两个,但有一个在主函数外面,属于全局变量,一个在main函数内部,属于局部变量,虽然没出错,但是建议还是定义不同的变量,避免引起歧义。
在输出global的值时优先选择了局部变量的值进行输出。
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用
的而限定这个名字的可用性的代码范围就是这个名字的作用域。
怎么理解呢?其实变量的作用域就是你所作用的范围,出了这个范围就不管用了。
局部变量:作用域是变量所在的局部范围。
全局变量:作用域是整个工程。
生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
这个也不难理解,就是你什么时候生,什么时候亡。
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
全局变量的生命周期是:整个程序的生命周期。
常量的分类也有几种:
1.字面常量(就是普通的常量 如 78;)
2.const 修饰的常变量(实际上属于不能改变的变量)
3.#define 定义的标识符常量(宏)
4.枚举常量(定义枚举类型的常量)
#include
#define MAX 100//宏,属于预处理命令,后续可直接用MAX这个常量
enum color
{
RED,
BLUE,
GREEN,//像 RED,BLUE,GREEN,PINK,YELLOW这些就是枚举类型的常量
PINK,
YELLOW
};
int main()
{
//字面常量
660;
1800;
//const修饰的常变量
const float salary = 8888.8f; //这里的salary是const修饰的常变量且第一次赋值后无法修改
printf("max = %d\n", MAX);
//枚举常量
printf("%d\n", RED);
printf("%d\n", BLUE);
printf("%d\n", GREEN);
printf("%d\n", PINK);
printf("%d\n", YELLOW);
//枚举常量的默认是从0开始,依次向下递增1的
return 0;
}
"一给我里giaogiao!\n"
像这种用双引号包裹起来的一串字符就叫做字符串,其实在"一给我里giaogiao!\n"这个字符串结尾还隐藏有’\0’这个转义字符,'\0’是字符串结束的标志,但并不算是字符串的内容。
#include
//下面代码,打印结果是什么?为什么?(突出'\0'的重要性)
int main()
{
char arr1[] = "bit";
char arr2[] = {'b', 'i', 't'};
char arr3[] = {'b', 'i', 't','\0'};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
上述代码的输出结果如下:
bit
bitbit
bit
为什么arr2在打印字符串内容的时候出现了bitbit,因为\0是字符串结束的标志,arr1内容是字符串,默认后面有\0作为结束标志;而arr2内容是三个字符bit,并没有遇到\0这个转义字符,在打印的到最后一个字符t的时候不会停止,会继续向下打印,直到遇到\0才停止打印,所以会出现bitbit的打印内容。同理,在arr3加上\0这个转义字符时,就停止打印,所以arr3会打印出bit的内容。
这里随便列举两个转义字符做解释
如\ddd代表八进制数,'\111’转化为十进制就是73,查询ASCII表得知对应I这个字符
这里也可以用代码验证一下
#include
int main()
{
char a='\111';
printf("%d\n",a);
printf("%c\n",a);
return 0;
}
运行结果为
73
I
可以看出用%c打印出的是字符I,对应的ASCLL码为73,所以%d打印出来的为整型73
下面我们来看一道小的程序题
#include
#include
int main()
{
printf("%d\n", strlen("abcdef"));
printf("%d\n", strlen("c:\test\628\test.c"));
return 0; }
思考一下,结果是什么,注意strlen是库函数,需要引入string.h这个头文件,strlen用来计算字符串的长度,那么自然\0是不算在内的,它只是一个结束的标志。
运行结果为
6
14
第一个很好理解,abcdef六个字符
第二个,c是一个:是一个\t是一个e是一个s是一个t是一个\62是一个8是一个\t是一个e是一个s是一个t是一个.是一个c是一个,所以一共是14个字符长度。有人说\628不是表示吗?不是的,既然是八进制,\ddd中的数是0~7的,所以\62算一个,8又算一个。
注释有两种基本的方式
//这是一行注释
/*这也是我的注释*/
#include
int main(){
printf("大家好!我是练习时长两年半的个人偶像练习生:\n");
return 0;
}
顾名思义,就是按照书写的顺序,一条一条语句自上而下执行,属于最基本的也是最简单的程序结构。
if…else就是一个简单的选择语句
#include
int main(){
int money=9999;
if(money>8888){ //如果money>8888,则选择爱你一万年这个分支
printf("爱你一万年");
}
else{
printf("爱你三千遍"); //如果money<=8888,则选择爱你三千遍这个分支
}
return 0;
}
循环结构包括for循环,while循环和do…while三种基本的结构
#include
int main()
{
int i=1;
int sum=0;
for(i=1;i<=10;i++){ //for循环
sum+=i;
}
printf("1到10的和为%d",sum);
return 0;
}
上述代码用一个简单的for循环计算了1到10得和,结果为55
简单解释一下,i=1时,判断是否i<=10,若是,sum=0+1=1;
接着下一次循环,i先加1变为2,判断是否i<=10,若是sum继续=1+2,
直到 i 累加到11不满足条件,退出循环,输出sum的值。
#include
int main()
{
int a=1;
int sum=0;
while(a<=100){ //while循环
sum+=a;
a++;
}
printf("sum=%d",sum);
return 0;
}
上述代码是一个简单的计算0到100之和的while循环
当a<=100时进入while循环,sum开始累加,a也开始累加,直到a=101时,不满足条件,退出循环,输出sum的值为5050。
#include
int main()
{
int a = 1;
do{ //do...while循环
a++;
}while(a < 10);
printf("%d",a);
return 0;
}
do…while不同于while循环的是,do…while是先做在判断
上述程序,当a累加到10的时候,不满足条件,退出循环,输出a的值为10
main为主函数,每个程序必不可少的
自定义函数分为有参函数和无参函数
这里就举两个简单的了解了解
#include
int sum(){ //无参函数,int为返回值的类型,sum为函数名,()中为形参,没有参数传递就不写
int i, sum=0;
for(i=1; i<=100; i++){
sum+=i;
}
return sum;
}
int main(){
int a = sum();
printf("The sum is %d\n", a);
return 0;
}
运行结果为The sum is 5050
注意:这里定义了一个sum函数用来返回1到100的和,没有进行参数传递,属于无参函数;函数定义在main函数之上不需要进行函数声明,否则需要进行函数声明。
# include
int main(void)
{
int Max(int x, int y); //对Max函数的声明, x、y称为形参
int a = 1, b = 2;
printf("max = %d\n", Max(a, b)); //a、b称为实参
return 0;
}
//定义Max函数
int Max(int x, int y)
{
int z; //函数体中的声明部分
if (x > y) //下面是语句部分
{
z = x;
}
else
{
z = y;
}
return (z); //返回z的值给主调函数使用
}
上述函数为有参函数,用来返回两个数中的最大值,运行结果为max = 2
C语言中给了数组的定义:一组相同类型元素的集合
这样如果我们想存1到10十个数就可以用一个数组存储起来。
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
//当然数组长度10也可以省略
int arr[] = {1,2,3,4,5,6,7,8,9,10};//也是合法的
数组的使用,数组可以用arr[0]来访问第一个数组元素,注意不要出现越界访问。
#include
int main()
{
int i = 0;
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个数组arr
for(i=0; i<10; i++)
{
printf("%d ", arr[i]); //依次输出第i+1个元素
}
printf("\n");
return 0; }
上述代码定义了一个长度为10的数组arr,存储1-10,十个元素
用一个for循环循环10次,依次输出数组中的十个元素。
之后在深入了解细节。
C语言的操作符有很多,不同运算符优先级也有所不同,有些语法还是需要我们多多注意的。
这些运算符以后我会专门开一个专题进行讲解,小伙伴们先走马观个花,因为前期还是了解为主,以后多学多用就掌握的差不多了。
C语言自身提供了大量的关键字,这些关键字是预先设定好的,用户自己不可以创造关键字。
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
计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如 int 占用 4 个字节,char 占用 1 个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就像门牌号、身份证号一样,每个字节的编号是唯一的,根据编号可以准确地找到某个字节。
我们将内存中字节的编号称为地址(Address)或指针(Pointer)。地址从 0 开始依次增加,对于 32 位环境,程序能够使用的内存为 4GB,最小的地址为 0,最大的地址为 0XFFFFFFFF。
#include
int main()
{
int num = 10;
int *p = #//定义了一个指向 int 类型数据的指针变量p,并指向num变量的地址
*p = 20;//把p指向的num的变量修改为20
printf("%d",num);
return 0;
}
指针大小是由当前CPU运行模式的寻址位数决定!
如32位系统是从00000000000000000000000000000000到11111111111111111111111111111111,一个指针变量的大小是32位(bit),也就是4个字节(byte),而在64位系统下大小为8个字节。
C语言还引入了结构体这个概念
前面我们讲解了数组(Array),它是一组具有相同类型的数据的集合。但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放。所以引入了结构体这个概念。
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
};
这样以后我们就能用struct stu这个类型来定义别的变量了
使用方法和int,float一样
struct stu stu1={‘a’,99,18,‘8’,‘99.9f’};就定义了一个结构体变量stu1并完成了赋值操作。
stu1.name;//用来访问stu1中的name变量