手把手带你初识C语言

初识C语言

特别特别特别细的知识点,对小白特别特别友好

大家多多指正,多多支持

一、什么是C语言?什么是计算机语言?

计算机语言是人和计算机交流的语言,常见的有C,C++,Java,Python,go等,
C语言是一种计算机语言,常用于底层开发(驱动——>操作系统——>应用软件,在操作系统及以下就是底层开发,比如Linux操作系统大部分是用C语言写的,游戏引擎大多用C或者C++ 写)
国际标准:ANSI C;常用的是C89,C90标准
常见编译器:Clang(苹果),GCC(linux),MSVC(VS2022,集成开发环境)…

如何写下你的第一个C语言代码?

1、下载好你的编译器(本人目前使用VS2022)
2、点开编译器,依次点击:创建新项目,空项目(C++的空项目),下一步,项目名称(起一个有意义的名字,一般都是日期或者内容,不要随便乱写,建议用英文),位置(一般都会统一存放到一个文件夹里),创建,OK项目创建完毕。
2.5、【注意】如果你没有看见解决资源管理器,那么可以点击视图,再点击解决方案资源管理器。
3、创建源文件:右击源文件(后缀为.c的文件,.h的文件为头文件),点击添加,点击新建项,点击C++文件(因为C与C++不分家,VS只有C++选项),更改名称(注意后缀为.c,如果要写C++的程序,那么后缀为.cpp),点击添加,OK创建完毕。
4、写一个C语言代码(注意:全部字母和符号都是英文的),打印Hello World:

#include <stdio.h>//include表示包含,下面的代码包含了<stdio.h>这个头文件,stdio=standard input output即标准输入输出头文件
int main()//主函数
{
	printf(“Hello World”);//printf是一个打印函数,专门用来在屏幕上打印数据的,printf是C语言标准库中提供的一个库函数,可以直接使用,但是在使用前需要引头文件stdio.h
	return 0}

5、想要运行程序,键盘按住Ctrl+F5,如果看到屏幕上有东西一闪而过,那么请点击:属性->链接器->系统->子系统->控制台

二、mian函数

mian函数叫作主函数,是一个程序的入口,C语言的一个项目中有且仅有一个主函数,一般定义主函数的类型为int(整形),后面与return 0相呼应,即
int mian()
{
return 0;
}

三、数据类型

常见数据类型:
int:整型(整数)
char:字符数据类型(比如abcd=-*/+…)
short:短整型
long:长整型
longlong:更长的整型
float:单精度浮点型(小数)
double:双精度浮点型
这些类型的变量占内存多大的空间呢?我们用一下代码来实现:

int main()
{
	printf("%d\n",sizeof(char));//结果是1,单位是字节//%d表示打印整型变量;\n是一个转义字符(后面详解),作用是换行;sizeof是一个操作符,用来计算变量的大小的
	printf("%d\n",sizeof(short));//2
	printf("%d\n",sizeof(int));//4
	printf("%d\n",sizeof(long));//4;C语言标准规定sizeof(long)只要大于或等于sizeof(int)即可
	printf("%d\n",sizeof(long long));//8
	printf("%d\n",sizeof(float));//4
	printf("%d\n",sizeof(double));//8
	return 0;
}

数据类型是用来创建变量的,下面是一些变量的定义格式以及打印是用的符号:
1.字符型:
char ch=‘w’(char是数据类型,ch是自定义的变量名称,用’ ‘(单引号)引起字符);用%c打印字符类型数据:printf("%c",ch);
2.浮点型:
float a=75.5f;用%f打印单精度浮点型:printf("%f",a);
double b=75.5;用%lf打印双精度浮点型:printf("%lf",b);
【注意】浮点型数据在内存中不会精确储存
3.整型:int a=0;
【补充】对于printf在打印时,%d打印的是十进制整型,%c打印的是字符,%s打印的是字符串,%f打印的是单精度浮点型,%lf打印的是双精度浮点型,%o打印的是八进制整型(如果是%#o则打印的是带有前导0的八进制整型),%x打印的是十六进制整型(%#x同理)

四、变量

1.创建变量的方法

(见上文,一般在定义变量的同时要给它进行初始化,一般就=0)

2.变量的命名:

仅能用字母(大小写,大写与小写是不一样的),数字(不能以数字开头)以及下划线_来命名,长度不能超过63个字符,变量名不能为关键字(后面详解)

3.变量的分类:局部变量,全局变量

局部变量:放在一个{ }内部
全局变量:在{ }外部
当全局变量和局部变量的名称重复时,局部变量优先,但建议不要冲突

#include <stdio.h>
int main()
{
    int a=0;
    int b=0;
    int sum=0;
    scanf("%d %d",&a,&b);//scanf为一个输入函数。对于VS编译器,输入函数scanf会被识别为不安全的函数,但是scanf是C语言标准库中定义的函数,而scanf_s是编译器自身定义的函数,所以如果按照VS的指示使用scanf_s替换scanf的话可能导致该代码在其他的平台不兼容,所以可以根据报错提示在项目第一行输入:#define _CRT_SECURE_NO_WARNINGS 1就可以让VS忽略警告
    sum=a+b;
    printf("%d",sum);
    return 0;
}
4.变量的作用域

作用域是程序设计中的一个概念,一般来说,一个程序代码中所用到的名字(自己定义的变量的名称,也就是相当于这个变量)并不是总是有效的/可用的,而限定这一名字可用性的代码范围就是这个名字的作用域。对于局部变量,作用域为变量所在的局部范围之内;全局变量的作用域是整个工程【可以定义在该源文件(test.c),也可以定义在其他的源文件(add.c)里,但是在test.c中使用是要先声明:extern (专门用来声明外部符号的关键字),如exturn int a(int a)来自于其他的源文件】。

#include <stdio.h>
int main()
{
    {
        int a=10;//定义一个局部变量a    
        //一个{}是一个代码块,局部变量的作用域就是在{}之内
    }
    printf("%d",a);//报错:未定义的标识符a,原因是a是一个局部变量,当它出了它的作用域之后就会自动销毁
    return 0;
}
#include <stdio.h>
int a=100;//全局变量,可以在main函数中使用
void test()
{
    printf("a=%d",a);//打印出来为a=100
    //此处不解释该函数意思,定义这个函数是为了解释全局变量可以在其他的函数中使用
}
int main()
{
    printf("%d",a);//打印出来为100
    test();//此为函数的调用,后面详解
    return 0;
}
#include <stdio.h>
int a;//此为变量的声明,不是定义
void test()
{
    printf("%d",a);
}
int a=100;//会有警告:为声明的标识符,一般来说全局变量要定义在函数的前面,因为电脑扫描代码的时候是从上往下扫描的,所以如果执意要将变量定义在函数后面,我们可以在前面添加一个声明:int a;
int main()
{
    printf("%d",a);
    test();
    return 0;
}
5.变量的生命周期:

指的是指变量创建到变量销毁的时间

五、常量

1.字面常量:

就是简单的一些常量,比如说:整型字面常量:3;浮点型字面常量:3.14;字符型字面常量:‘a’;字符串型字面常量:“abcde”;

2.const修饰的常变量:

(常变量:虽然不可改变,但是本质还是变量)

#include <stdio.h>
int main()
{
    const int num=100;
    num=200;//此时编译器会报错,原因是当const修饰了num是,num的值不可改,也就不能再将200赋给num,此为const修饰的常变量的常属性的表现
    return 0;
}

我们知道,在定义数组的时候,确定数组元素个数的时候应该输入常量表达式,对比一下两段代码,我们就可以体会出来const修饰的常变量的本质

#include <stdio.h>
int main()
{
    int arr[10]={0}//int表示数组里面存放的元素的类型,arr是自定义的数组名,10表示数组元素个数,{0}表示数组存放的元素都为0
    return 0;
}
#include <stdio.h>
int main()
{
    const int n=10;
    int arr[n]={0};//此时编译器会报错:请输入常量表达式,由此可见,由const修饰的常变量在本质上还是变量
    return 0;
}
3.#define定义的标识符常量:

如#define M 100(M是我们定义的标识符,值是100) ,可以用来指定数组的大小

4.枚举常量:

有些东西我们可以一一列举出来,那么我们就可以把它定义为枚举常量。

enum Color//enmu是枚举关键字;下面包括的内容就是枚举类型Color的可能取值,是常量,叫做枚举常量
{
    Red,
    Green,
    Blue,
}//这三个枚举常量会有赋值,分别为0,1,2

六、字符串

由双引号引起来的一串字符叫做字符串,比如:“helloabc”,字符串的结束标志是:\0(转义字符),不算作字符串的内容
我们存放字符串通常是存放在一个数组里面:

int mian()
{
    char ch1[3]={'a','b','c'};//该数组里面有三个元素,在[]里不写元素个数也是一样的,电脑会默认为它分配三个字节的空间:char ch[]={'a','b','c'};
    char ch2[]="abc";//ch1数组和ch2数组不一样,ch2中不仅存放了abc三个字符,还默认放了一个\0
    return 0;
}

在这里插入图片描述
当我们在打印ch1数组和ch2数组时,会出现下面这种神奇的现象:

在这里插入图片描述
出现一段乱码的原因是什么呢?
当我们在打印字符串的时候,要遇到了\0这一结束标志后才会停止。
而我们ch1数组中只存放了a,b,c三个字符,没有\0,所以printf会在内存中持续地读取数据,直到遇到\0之后才会停止下来,而这三个字符和\0之间可能存在的就是一些随机值,所以打印出来是乱码。
而ch2数组中存放了一个字符串,字符串的结尾有一个默认的\0存在,所以当打印了abc三个字符后就会停止。
仔细观察一下两个代码的打印结果,结果非常的amazing啊
在这里插入图片描述
在这里插入图片描述
在计算字符串长度的时候,我们要用到strlen这个库函数:

#include <string.h>
#include <stdio.h>
int main()
{
    char ch1[]="abc";
    char ch2[]={'a','b','c'};
    char ch3[] = { 'a','b','c' ,'\0'};
    int len1=strlen(ch1);
    printf("%d",len1);//打印出来是3,也就是strlen统计的是\0前面的字符个数
    printf("%d",len2);//打印出来是一个随机值,理由同上
    printf("%d",len3);//打印出来结果是3
    return 0;
}

七、常见的一些转义字符:

转义字符是字符
\?:在书写连续的多个问好时使用,防止它们被解析为三字母词
':用于表示字符常量(一般在使用单引号时都要成对使用,加上一个\可以让其单独使用)
":用于表示一个字符串内部的双引号
\:用于表示一个反斜杠,防止它被解释为一个转义序列符,比如说,我们要输入\t,为了防止它被解析为转义字符,呢么我们就可以写:\t
\a:警告字符,蜂鸣
\b:退格符
\f:进纸符
\t:水平制表符
\v:垂直制表符
\r:回车
\0:字符串结束标志
\n:换行
\ddd:表示一到三个八进制数字
\xdd:dd是两个十六进制数字,转化为ASCLL码值
简单解释一下\ddd:其中的ddd表示一个八进制数字,打印出来的结果是该八进制数字转化为十进制数字之后所对应的ASCLL码值
在这里插入图片描述

而ascll表最多只有127个编号,对应的八进制数字为177,对应的十六进制数字为7F
【补充】在表示八进制数字和十六进制数字的时候需要分别加上前导0和前导0x(x有大小写之分,如果x是小写,那么打印出来的十六进制中的字母就是小写的;如果x是大写,十六进制中的字母就为大写);

在这里插入图片描述

【补充】字符’0’的本质是48;转义字符’\0’的本质是0;数字0的本质就是0

八、注释

解释语句,屏蔽一些不用的但是不想删掉的代码
C语言的注释风格:* *\ 不支持嵌套注释
C++的注释风格:\ 支持嵌套

九、选择语句

1、if语句:

格式:1.if(条件语句)执行语句
2.if(条件语句)执行语句;
else if(条件语句)执行语句;
else 执行语句;
3.还可以有多个else if
当条件语句为真(在C语言中,一切非0的值都为真)的话,那么就会执行该条件语句下的语句。

2.switch语句

十、循环语句

1、while循环语句:

格式:while(判断条件)
{
循环体
}
当判断条件为真的时候就会进入循环体,条件为假,那么就跳出循环

2、for循环
3、do-while循环

十一、函数

定义函数:
格式:函数返回类型 函数名称(输入参数)
{
函数内容;
}
一个函数可以在多个地方调用,大大提高了效率
比如,我们写一个计算两个数的和的函数:

#include<stdio.h>
int Add(int x,int y)
{
int z=0;
z=x+y;
return z;
//这里也可以写return (x+y);
}//其中Add是我们自己取的函数的名称,Add中的变量是整型,所以前面加上int;int x和int y是函数的形参,

int main()
{
    int a=0;
    int b=0;
    int sum=0;
    scanf("%d %d",&a,&b);
    sum=Add(a,b);
    printf("%d",sum);
    return 0;
}

十二、数组

概念:
数组中可以存放一组类型相同的元素
初始化:
完全初始化:数组中的每一个元素都有输入的初始化的值,如下图数组arr2
不完全初始化:整型数组剩余的默认初始化为0(如下图arr1),字符型数组剩余的默认初始化为\0
在这里插入图片描述

如何访问数组里面的元素:
数组中的元素都有下标,第一个元素的下标为0,依此类推。如果想访问数组中的元素,那么可以通过下标来访问

#include <stdio.h>
int main()
{
    int i=0;
    int arr[10]={1,2,3,4,5,6,7,8,9};//这里的10是指定元素个数
    while(i<10)
    {
        printf("%d",arr[i]);//i指的是下标,和指定元素个数的10不一样
        i=i+1;//这样就可以访问数组中的所有元素    
    }
    return 0;
}

十三、操作符

操作符有很多分类,下面只讲了一些常见的分类

1、算数操作符
      • / %
        /:两端如果是整数,那么执行整数除法,也就是结果保留整数位;如果要有小数,那么除号两端必须有一端是浮点型,打印出来才是小数
        %:取模,也就是取余数,%操作的两个操作数必须是整数
2、移位操作符

<< >>

3、位操作符

& ^ |

4、赋值操作符

==
/=
%=
&=
^=
|=
<<=
= += -=

解释:=在这是赋值,==才是判断相等;a=a+5可以写成a+=5;a=a-3可以写为a-=3,*=,/=,%=同理,其余的后面详解

5、关系操作符

<= = >= <= !=(不相等)

6、逻辑操作符

&& 逻辑与(并且,当且仅当两边同时为真时结果才为真)
|| 逻辑或(或者,当且仅当两边同时为假的时候结果才为假)

7、 条件操作符

exp1 ? exp2 : exp3(当表达式1为真的时候,执行表达式2,忽略表达式3;如果表达式1为假的话,执行表达式3,忽略表达式2)

8、单目操作符

单目操作符就是只有一个操作数
逻辑反操作!:将真(非0)变为假(0),把假变为真
-负值,
&取地址操作符,
*解引用操作符,
sizeof:求操作数的类型长度(以字节为单位),是计算变量所占内存空间大小的操作符(注意sizeof和strlen的区别:strlen是库函数,用于计算字符串长度,统计的是字符串中\0之前的字符个数)
++:后置++:先使用,再++; 先使用a的值让b=100,a再自增
在这里插入图片描述
前置++:先自增,再使用
在这里插入图片描述
–:同理
(类型):强制类型转换(括号里面放一个想要转换成的类型)
9、双目操作符;三目操作符
10、逗号操作符
11、下标引用操作符[ ];函数调用操作符( );结构成员操作符. ->

十四、关键字

C语言给我们提供了很多的关键字,不能自行创建,定义变量名称是不能使用关键字

用于定义函数类型的:

float;short;int;double;long;longlomg;
signed(有符号的);unsigned(无符号的,就是恒为正);
static(静态的,有三种用法:1.修饰局部变量时,让其不再销毁;2.修饰全局变量;3.修饰函数);
1.对于局部变量a,每次在进入范围时创建,出局部变量的时候销毁,所以打印出的a的值都是1,而对于有static修饰的局部变量b,在每次出局部变量范围时不会被销毁,b保留了原来的值,所以函数在不断调用的时候,b的值会不断的自增
在内存中有几个区域,栈区,堆区,静态区。例如局部变量、函数参数这些临时的变量都是放在栈区的,堆区是用来动态内存分配的,静态区放的是静态变量和全局变量。放在静态区的变量创建后直到程序结束才释放,而一个局部变量用static修饰时,就是把该变量放到了静态区中。被static修饰不会影响作用域,生命周期发生了变化。
2.全局变量本身是具有外部链接属性的(在a文件中定义的变量,可以在b文件中通过链接使用),当全局变量被static修饰时,这个属性就变成了内部链接属性,这个全局变量只能在自己所在的源文件中使用,最终使得全局变量的作用域变小
在这里插入图片描述
3.static修饰函数时和全局变量相似,函数本身是具有外部链接属性的,当函数被static修饰时,这个属性就变成了内部链接属性,这个函数只能在自己所在的源文件中使用,其他源文件无法使用。
void(无返回类型的);
const(常变量);
enum(枚举关键字);
union(联合体);struct(结构体);
typedef(类型定义,类型重命名,当我们觉得某一个类型的名称过于复杂,我们可以给他重命名,时期简单化);auto:自动变量(自动创建自动销毁,加在局部变量之前,但一般都省略掉了,局部变量又叫做auto变量)

用于循环语句的:

break;continue;for;do;while

用于分支语句的:

if;else;switch;case;default;break;goto

其他的一些关键字:

extern(声明外部符号);
register(寄存器是我们电脑中访问速度很快的,空间很小的一个存储数据的地方,我们想要把什么数据放到寄存器中时,可以在变量前面加上一个register,就可以建议电脑把该变量放在寄存器中,但是现在的编译器一般都会通过分析后把一些数据放到寄存器中以提高代码运行效率,所以现在这个关键字不怎么使用了);return;sizeof;volatile

十五、#define定义常量和宏

#define可以定义符号和宏
比如:#define M 100定义一个名叫M的符号,M的值是100
宏是有参数的,与函数非常的类似,但宏一般用于处理非常简单的问题,而函数可以处理复杂的问题
比如:#define Max(x,y) (x>y?x:y)Max是定义的宏的名字,x,y是宏的参数,括号里的x>y?x:y是宏体
再比如:#define ADD(x,y) ((x)+(y))用于求和,为什么x和y要加括号,以后详解

#include <stdio.h>
#define Max(x,y) (x>y?x:y)
int main()
{
    int a=20;
    int b=10;
    int m=Max(a,b);
    printf("%d",m);
    return 0;
}

十六、指针

程序运行时会载入内存,程序中如果有数据需要存储也会申请内存空间,如何有效的使用内存呢?内存被划分为了很多个小的内存单元,同时给每个内存单元编了号,当我们想要找某个内存单元时我们就可以通过内存编号去找。在实践中一个内存单元的大小是1字节。内存单元的编号也被称为地址,又叫指针。
那么,如果想要访问一个内存单元,那么这个指针如何产生呢?
我们的电脑一般有两种,一种是32位架构计算机,一种是64位架构计算机。以32位机器为例,它有32根地址线,地址线如果通电,就会有不同的电信号,电信号转化为数字信号就会产生232种二进制序列,也就可以作为232个地址,就最多可以管理232个内存单元,也就是最多能够管理232字节的内存空间。2^32byte=4GB
如何看地址呢?

#include <stdio.h>
int main()
{
    int a=1;
    printf("%p\n",&a);//%p是用来打印地址的,&是取地址符号,&a就是a的地址;但是我们打印出来会发现只有一个地址,这不合理啊,a是一个int类型的变量,应该占4个字节呀,为什么只有一个地址呢?其实啊,&a打印出来的地址是a所占内存空间的第一个字节的地址
    return 0;
}

在这里插入图片描述
那我们知道了地址有什么作用呢?
我们可以通过地址找到这个变量。(就相当于我们有了一个人的门牌号,我们可以通过门牌号找到他)
在这里插入图片描述
指针变量的大小4个字节,不管指针变量所指的变量是什么,因为地址大小是不变的,只是在32位机器(存放的是32bit的地址)和在64位机器(存放的是64bit的地址)上大小有所不同,一个是4字节,一个是8字节

十七、结构体

为了能够让C语言描述复杂对象,C语言提供了一些自定义的类型来描述对象,比如枚举,联合体,以及结构体。结构体的关键字叫:struct
在这里插入图片描述
.就是结构成员操作符:结构体变量.成员名

在这里插入图片描述
了解即可。

  • 36
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值