C语言初阶入门-初识C语言

1、什么是C语言?

 C语言是一种面向过程的计算机语言,与C++、java等编程语言一样用于人与计算机交流,广泛用于底层开发。C语言是一种高级计算机语言,计算机语言经过几十年的发展由复杂难懂的二进制指令逐步发展成为C语言,C语言不断完善和更新,同时制定相应的标准就成了我们如今使用的C语言。现在C语言常用的标准有ANSI C、C89、C90等,常用的编译器有Clang、GCC、MSVC等。C语言的发展大家可以在网络上找到详细的资料。

2、第一个C语言程序

在这里我用的是vs2022来写第一个C语言程序,在写代码之前,我们要先创建工程,首先打开vs2022,点击创建新项目,之后选择空项目,然后自己输入项目名称,选择位置,文件位置最好是在桌面上创建一个文件夹专门用来保存代码,终于更方便后续的查找和修改。f695e1c9051940dcb8909af5459496db.png

02834e452d5549b59ef78f17f4d16ebd.png 

bb092bedd69748aa8477b13369bc37aa.png 

创建完项目后,此时项目里面还是没有文件的,我们需要找到解决方案资源管理器中的源文件,右键点击添加新建项,之后点击C++文件,名称后缀改成.c,如果是.cop文件则会按照C++的语法编译,.c文件才会按C语言语法编译。6850b169e174488c8f60b7cad8d952e3.png

d743d09094694491982c722f4369fd8b.png 

3525406ff69a49139a2a5832294378aa.png    

 

创建完源文件就可以开始写代码了,首先写一个C语言标准的main函数,如下图

3ba0719d47244ed3918dd3596f9ffcf6.png

需要注意的是 在写代码的时候输入法一定要用英文。main函数类型是int,返回值是0,这是一种历史遗留习惯,程序运行正常就return 0,异常就return 1。C语言规定main函数是程序执行入口,可以按f10观察。

第一个程序我们可以用printf函数在屏幕上打印一个"hello world",如下图

9385bd4f652c43fe87d46311d9f99806.png

在该代码中,我们用了printf函数来打印一串字符,printf函数是stdio库中的库函数 ,所以在main函数之前要引用头文件,#include<stdio.h>,在用库函数的时候,我们都要先引用头文件。

 

3、数据类型。

学习C语言绕不开数据类型,写代码是为了解决生活问题,小数(浮点型),整数(整型),字符,这几类数据在生活中绕不过去。浮点型有float(单精度浮点数),double(双精度浮点数),整型有short(短整形),int(整型),long(长整型),long long(更长的整型)。用printf打印整数的时候可以这么写printf(“%d\n”,100),其中%d是打印整型,\n换行。我们可以用sizeof函数来看一下每个类型所占内存的大小,当sizeof函数参数是数据类型的时候返回值是该数据类型所占内存,返回的是一个无符号整型,用%zu打印,单位是字节。

64991e5c501f478b9e35845baa8e2d28.png

 

我们的世界是十进制,计算机是二进制(01),二进制一个0或1就是一个bit位,一个byte是8个bit,1kb=1024byte,1mb=1024kb,gb、tb、pb以此类推。 

一个字节是八个比特位,由上图可知,char一个字节,short两个字节,int和long都是四个字节,C语言规定sizeof(long)大于等于sizeof(int)就行,long long是八个字节,float四个字节,double八个字节。数据大小不同,要求的精度不同,用不同的数据类型可以更好的满足需求,同时避免空间浪费。

 


4、变量和常量。  
程序中存放数据要向内存申请空间,用类型定义一个变量来存放数据,创建变量的本质就是向内存申请空间。

生活中有一些不变的量比如身份证号码、圆周率,也有变化的量比如年龄、身高。不变的量就是常量,变化的量就是变量。
定义变量取名时要注意可读性,尽量用英文命名。

4.1变量 分为局部变量和全局变量。
主函数大括号外面定义的是全局变量,大括号内部定义的变量是局部变量。在一个函数内变量不能重定义,当全局和局部变量重名时,局部优先,但是建议不要重名,便于理解代码。
变量的使用,建议创建变量时初始化,不初始化默认是随机值。
举例变量使用,如下图我们用简单的函数实现加法,

502d269681444a97bf899997630e517b.png
我们可以用输入函数scanf(“%d %d”,&num1,&num2),%d表示从键盘读取的数据类型为整型,将读取的数据放进变量中要用到取地址符号。

 

变量的作用域和生命周期。
变量的作用域就是限定这个变量的代码可用范围。在某个范围内申请的变量出了这个范围就不能用了。
局部变量的作用域就是它所在的局部范围,出了它所在的大括号就无效了。
全局变量的作用域是整个工程。

变量的生命周期
局部变量的生命追周期是进入作用域生命周期开始,出作用域生命周期结束
全局变量的生命周期是整个程序的生命周期。


了解变量作用域和生命周期的意义是知道什么时候可以用这个变量,什么时候用不了,严格来讲可以说变量的作用域约等于生命周期。

 

4.2    C语言中常见的四种常量

  字面常量:字面常量就是具体的数,单引号括起的字符,双引号括起的字符串如3.14,’w’,”abc”。

  const修饰的常变量:变量初始化之后我们是可以更改的,而创建变量时用const修饰的话它就是一个常变量,不能修改,如const int a=3; 。在C语言中,const修饰的a本质是变量,但是不能被修改,有常量的属性。如在创建数组时,const int arr[n]也是会报错的。记住,常变量本质上还是一个变量。

  define 定义的标识符常量:如#define MAX 100;

  枚举常量:enum Color
{
RED,
GREEN,
BLUE
};

 


5 字符串、转义字符、注释
5.1 字符串
C语言给了我们一种字符类型char,也有一种字符常量:单引号括起来的单个字符。如果一个变量要放一串字符,C语言里面称其为字符串,用双引号括起来,如“abcd”。C语言中没有字符串类型,这种由双引号引起来的一串字符成为字符串字面值,简称字符串,是字面常量。于是我们用字符数组来创建一个变量储存字符串,如char str[10]=“abdcds”,字符串大小不能超过数组大小,如果不确定字符串大小可以在创建数组时省略数组长度如char str[]=“andhdh”。有一点需要注意的是,数组下标是从0开始,字符串结束标志是’\0’。当这样创建数组时char arr[]={‘a’,’c’,’s’}时,不会主动添加‘\0’,如果不手动添加’\0’,由于内存是连续的,如果打印这种没有结束标志地字符串时,printf会一直向后读取直到遇到’\0’。从这种情况更能认识到字符串结束标志的重要性。

如果我们想查看字符串或者数组内部的详细情况,在我所使用的vs2022里,可以ctrl f10进入调试后,点击调试中的窗口中的监视功能来查看字符串的详细情况,如果出现无法读取内存,说明还没调试到要查看的地方,可以继续f10往下走或者重新调试直接将光标移到return 0,这样就可以看到内存分配情况了。

5cb0f1f97f5c4e729a6f42e294ed5f67.png

 

 


strlen函数用来求字符串的长度,如int len=strlen(“wed”);strlen函数,len=3。注意,strlen数字符串长度也是看结束标志\0的,所以上述例子中的arr字符数组没有 \0 strlen也会继续往后数,直到遇到\0。
所以字符串后面的\0是十分重要的。


5.2 转义字符
 粗浅理解就是转变字符的意思。举例打印 abcn 与 abc\n ,  ab0ke 与 ab\0ke
以下是转义字符

1e8aca5d53604f1d854f2781567134a3.png

 


    \?     在早期的C语言中,有一些编译器存在一些三字母词,如??)会被解析成 ],??(会被解析成 [,这时候在?前面加一个反斜杠就能避免这种情况,当前的编译器已经不支持三字母词了。

    \’    有时候我们想要打印一个单引号,但是如果代码是printf(“%c”,’’’)的话,这时候会出现问题,前面两个单引号会被看成一对,于是可以在中间的单引号前加一个单引号。

   \”      与\’是一样的道理,用于打印一个双引号的时候。

插一个知识,printf打印的时候,
%d用于打印整型
%c用于打印字符
%s用于打印字符串
%f用于打印float类型的数据
%lf用于打印double类型的数据


\\       用于打印\0或\n的时候防止被解析为结束符或者换行符,尤其是打印文件路径的时候用的很多。


\a       打印\a会触发电脑的蜂鸣器。

\b与 \f用处不大,不常用。

\t         与tab的作用一样,\t在求字符串长度是也是算一个字符,但是他的效果相当于四个空格或者两个空格。


\ddd      ddd表示1~3个八进制的数,如printf(“%c”,’\130’),会打印一个X,八进制130转化为十进制是88,‘88’在ASCII编码中代表字母X 。

\xdd       dd表示两个十六进制数字,如printf(“%c”,’\x63’),打印出来字符c。

 


5.3    注释
当你不想要一段代码时可以在前面加上\ \将其注释掉,或者想要解释某段代码可以在后面加上\\再加上注释的内容,这是C++的注释风格,C语言的注释风格则是用\*和*\来括住要注释的内容。两者都很方便,但是C语言的注释风格有一点缺陷就是不支持嵌套注释。在我们写代码的时候写注释是一个很好的习惯,既可以很好的梳理我们的思路,同时当我们的代码过于复杂时,能更好的解释代码,当以后代码出问题时,更帮助我们更容易读懂,可读性更高。

 

 


6、选择语句
if(选择语句)
{
选择语句为真就执行,为假就不执行
}
else(多分支,小括号里也是选择语句)
{

}
else
{
如果前面的分支都没进去,可以进这个分支
}

选择语句还有switch语句。


7、循环语句
for循环,while循环,do…while循环

写一个代码举例实现循环和选择,

#include<stdio.h>

int main()
{
    int day = 0;
    int level = 0;
    while (1)
    {
        if (level >= 10)
        {
            printf("offer!\n");
            break;
        }
        else
        {
            printf("第 %d 天,level=%d,继续加油!\n",day,level);
            day++;
            level++;

        }
    }

    return 0;
}

9fa88a42152f42a8ba87fa817b5138ba.png

 


8   函数

如之前的sum求和
int Add(int x,int y)
{
return x+y;
}
int sum=Add(n1,n2);
函数的类型就是返回值的类型,如果无返回值函数类型为voidw函数名尽量贴合用处,参数的类型要对应,大括号里的是函数体。用函数更清晰,模块化。


9    数组
当我们要存放一组数据时,可以用到数组。C语言对于数组的定义是一组相同类型的元素的集合。
如int arr[10]={0,1,2,3,4,5,6,7,8,9};创建数组的时候向内存申请了一块连续的空间来存放这些数据,申请的内存大小取决于数组长度,同时,C语言语法规定数组每一个元素都是有下标的,下标是从0开始的,数组可以通过下标来访问,如arr[0]=0,arr[1]=1。


10、操作符

算术操作符       +  -  *  /  %
注意 除号 / 两端都是整数的时候,他执行的是整数的乘法。如果两端只要有一个浮点数,那他执行的是浮点数的乘法。%取模则是整数除法中的余数,取模操作符两个操作数只能是整数。

移位操作符
<<   >>这个用于二进制的左移右移

位操作符
&  |  ^也是用于二进制操作,后面再分析


赋值操作符
赋值操作符
=    +=   -=   *=    /=   &=     ∧=    >>=    <<=
在代码中有时候赋值a=a+3这种写法与a+=3是完全一样的,其他的操作符也是类似。


单目操作符(只有一个操作数)
!               逻辑反操作
-                 负值
+                正值
&              取地址    
sizeof     操作数的类型长度(以字节为单位)操作数可以是用类型创建的变量、数组,也可以是类型。
                   可以用sizeof(arr)/sizeof(arr[0])求数组元素个数


~              对一个数的二进制按位取反    
--             前置、后置--    
++             前置、后置++    
                  前置++是先++,后使用,举例int a=2; int b=++a;这时候就类似于a=a+1,b=a。a和b都是3
                  后置++是先使用,后++,举例int a=2;int b=a++;这时候类似于b=a,a=a+1,a=3,b =2
                  前置和后置——也是一样的道理。

*                 间接访问操作符(解引用操作符)

(类型)    强制类型转换
                当将一个浮点数强制转换为整型时,就是舍掉后边的小数,保留整数。

 


关系操作符
>    <    >=      <=      == (判断是否相等)   !=  

逻辑操作符
&&       逻辑与             可以理解为生活中的并且             两者同为真结果才为真,有假则假
| |         逻辑或             可以理解为生活中的或者            两者同为假结果才为假,有真则真


条件操作符(三目操作符)
exp1?exp2:exp3
表达式1为真,结果为表达式2,表达式1为假,结果为表达式3。


逗号表达式
exp1,exp2,exp3…expN
逗号表达式特点是从左向右依次计算,最终结果为最后一个表达式的结果。
如int a=9;
int b=8;
int c=(a+2,b+3,a+b);则c的最终结果为22。

下标引用,函数调用,结构体访问操作符
[ ]                ( )               .        ->    

 

 


11     常见关键字

000347d51a774a9e9f2a752bb2d22049.png

 

关键字时C语言内置的,不是自己创建而来也不能自己创建。

先介绍几个,剩下的后续再讲解。

首先是auto,这个关键字我们不常见,基本都隐藏了,比如我们创建一个局部变量时,他的生命周期是进入作用域就自动生成,出作用域就自动销毁。本质上所有的局部变量创建时前面都有一个auto,如auto int a,被称为自动变量,但是因为所有的局部变量都是自动变量,所以干脆就直接省略了,更加简洁。

break 用于跳出循环时使用,一般和for,while,do…while,continue一块用

case则是与switch组成switch   case default语句,同类型还有if  else,goto跳转语句

char、short、int、long、long long、float、double等都是C语言内置的数据类型关键字

const用于修饰变量,表示常属性的意思,变量不能被更改

enum枚举体,struct结构体,union联合体也是同一类型的关键字,后续会讲解

extern用于声明外部符号

register是寄存器关键字,static是静态关键字,用来修饰变量,决定其存在寄存器还是静态区

return是函数返回值会用到。

signed 有符号的    unsigned无符号的

sizeof计算类型大小的关键字

typedef 类型重命名

void 空,无,一般用于函数的返回类型和函数的参数

volatile多用于操作系统中,后期会讲解

要注意的是变量的名字不能是关键字,要避免出现这种情况。

 


下面详细介绍两个关键字

typedef顾名思义就是类型定义,这里应该理解为类型重命名。在写代码的时候,有些类型用起来太复杂,名字不够简洁,于是我们可以用typedef将该类型重命名,再使用这些类型的时候就会方便很多。常用于结构体,可以理解为给类型起了一个别名。typedef只能用于类型。


static 在C语言中,static可以用于修饰局部变量,称为静态局部变量,修饰全局变量,称为静态全局变量,修饰函数,称为静态函数。
修饰局部变量时,局部变量出了作用域不会被销毁,本质上,static修饰局部变量的时候,改变了变量的存储位置。内存里面有栈区、堆区和静态区,局部变量本来是放在栈区的,而栈区里面的变量的特点就是进入作用域创建,出作用域销毁,而static修饰后,局部变量被放在了静态区,而在静态区的数据在程序结束的时候才销毁。存储位置的改变,影响了变量的生命周期,变得和程序的生命周期一样。

static修饰全局变量时,这个全局变量只能在这个源文件内部使用,不能在别的源文件使用。正常情况下,全局变量放在静态区,同一工程内,全局变量是可以跨文件用的,只需要用extern声明,而用static修饰后就无法在他的源文件外面使用了。需要注意的是,全局变量是具有外部链接属性的,用static修饰后,改变了他的外部链接属性,他的作用域就只有这个源文件,而不是整个工程了。

static修饰函数和修饰全局变量一样,extern也可以声明函数,用static修饰后,就无法在外部文件使用了,与全局变量一样改变外部链接属性,用于缩小作用域。

缩小作用域有什么意义呢?
当变量的作用域很大时,比如是整个工程,那么在所有的源文件里面都可以更改他的值,这样是不安全的,当作用域缩小,既可以保护该变量,防止被随意修改,也能避免在其他源文件出现重名。


register,再讲register之前要先普及一个知识,电脑上的存储设备有四种,
硬盘、内存、高速缓存(cache)、寄存器(集成在cpu上),按顺序越往后存储速度越快,相对应的空间越小,造价越高。而计算机要处理数据时,cpu首先会从寄存器中读取数据,而后高速缓存将一些相关的数据传给寄存器补上被读取的数据,内存中也会将相关的数据往高速缓存里面传,这样的架构使得cpu处理数据的速度变快,电脑性能更好。
而我们用rehister修饰变量时,register的作用是建议将变量存在寄存器中,它只是建议,而不能决定。如果以后我们需要频繁用到某个变量时,我们可以用register修饰。但是现在的编译器已经很高级了,当我们电脑的寄存器有空缺时,它会自动将数据放到寄存器中处理。

 

 


12、#define定义常量和宏


#define定义标识符常量。#define NUM 100

#define定义宏。宏是有参数的,跟函数有点相似。#define  ADD(x,y)  x+y      宏包括宏名,宏的参数,宏体。宏的参数是无类型的,宏的工作原理是完成替换,将参数替换到宏体中得到结果。

 


13、指针

内存:要了解指针,我们先要学习内存,内存是一块很大的区域,为了有效地使用和管理内存,内存被划分为一个一个的内存单元,每个内存单元都有一个编号,一个内存单元大小是一个字节。比如我们使用三十二位电脑,电脑里面有地址线,地址线有高电平和低电平两种状态,也就是1和0,而三十二位机器就有三十二根地址线,每根地址线都有两个状态,看成二进制序列就有了一个三十二位的二进制序列,这三十二位二进制数总共可以表示2^32个数,这些数就可以成为我们划分内存的编号。按这样来说的话,我们的三十二位电脑可以管理2^32个字节的空间,也就是4294967296个字节,换算下来就是4Gb,我们一般将内存编号写成八位十六进制。
那就又有一个问题,为什么不用比特位作为内存划分的最小单位呢?比特位太小了,我们我们没必要将内存划分得那么细致,管理起来太过麻烦,就拿C语言来说,最小的数据类型char就要用到一个字节,也就是八个比特位,如果用比特位作为内存划分最小单位的话,这就需要八个内存编号,这其实是没有必要的,同时也造成了很多的浪费。综合考虑来说还是将字节作为内存最小划分更为合理。
创建变量是向内存申请空间,变量的地址就是申请到的第一个字节的地址。可以在调试窗口的监视和内存窗口看到。用printf打印地址是用%p。


如果我们要将变量的地址存到另一个变量中,要用到&操作符,变量类型为要取地址的变量的类型加一个*,例如

int a=3;

int * p=&a;

这里的p就是指针变量,* 说明p是指针变量,int说明p指向的对象是int类型的。我们知道了变量的地址就能通过地址来对变量进行操作,*p就可以对变量进行一系列的操作,*是解引用操作符,*p意思就是通过p中存放的地址,知道p所指向的对象。取地址拿到的是最小的那个字节编号


指针变量的大小,指针变量的大小并不是有指针所指向的变量类型决定的,而是有电脑环境决定的,不管是什么类型的指针,都是在创建指针变量,指针变量的大小取决于一个地址存放的时候需要多大的空间。三十二位电脑的指针大小为四个字节,六十四位电脑的指针大小为八个字节。


14、结构体
我们前面学到的几种数据类型都不足以描述一个复杂的事物,但是C语言给了我们自定义类型的能力,自定义类型中有一种叫做结构体,结构体就是将一些单一类型的组合在一起的做法。


结构体对象访问内部成员的操作符是 . ,写法是结构体对象.成员名。s.name
结构体指针访问内部成员的操作符是->,写法是结构体指针->成员名。ps->name,也可以(*ps).name,但是这种太啰嗦。

 

 

 

 

 

 

  • 27
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值