C语言基础

简介:

c语言在编程语言中是偏底层的语言,像JavaScript,以及java。都是在c语言的基础上编译出来的。像操作系统:unix ,linux ,windows都是依靠c语言开发出来的,使用c语言可以开发windows应用程序。在c语言中不像在javascript中那么随意,在c中每写一条语句都必须要以 ; 进行结尾。

c语言的编码方式:

c语言的编码方式,在用char类型声明的窄字符会使用到Ascll码,用char类型声明的窄字符串和在Wchar_t声明的宽字符和宽字符串都不使用Ascll码,对于wchar_t声明的宽字符和宽字符串一般使用UTF-16和UTF-32进行编码的,对于char类型声明的字符串是根据编译器或者源文件的编码方式去编码的由于编译器的不同使用的编码也不同 。

数据类型:

c语言的数据类型大体分为以下四种:

  • 基本类型

    基本类型又分为下边这几种:

    • 整型

      整型用: int 进行表示在内存中占4字节

      整型又分为下这两种:

      • 长整型

        长整型用: long 进行表示在内存中占8字节

      • 短整型

        短整型用: short 进行表示在内存中占2字节

    • 浮点型

      浮点型又分下边这两种:

      • 单精度浮点型

        单精度浮点型用: long 进行表示在内存中占4字节

      • 双精度浮点型

        双精度浮点型用: short 进行表示在内存中占2字节

    • 字符型

      字符类型使用 : char 进行表示在内存中占1字节

      这种用char表明的字符类型还有一种名称叫窄字符。

      像这个char只能处理ASCLL码有的在字符处理不了中文以及其他语言的字符


      对于像除了Ascll码值以外的字符我们用 : wchar_t 表示它在内存中占的位置由编译器决定。由于这种类型在的头文件中所以我们要引入这个头文件,另外如果我们在单个字符前面加上大写字母L 例: char str = L'A';那么这个字符就会变为宽字符。还有宽字符的输出用不到下面那个通用的输出方法,我们要用到wchar.h头文件中的putwchar()或者wprintf()函数。
  • 枚举类型

  • void类型:

    在javascript中void是一个运算符 它用于计算它旁白的表达式,无论表达式是什么它总是返回的是undefined

    void在C语言中它是无类型的也就是没有类型的。

  • 复合类型

数据类型转化:

对于数据类型转换又分为以下两种:

  • 自动类型转换:

    自动类型的转换是不需要我们去干预的,比如在赋值运算中,右边表达式的值与左边的数据类型不同会自动将右边表达式转换为跟左边一样的类型。

  • 强制类型转换:

    强制类型转换是我们自己去进行的转换转换方式式这样的:(新类型) 表达式

对于自动和强制类型转换都只是根据需求时去进行的临时转换,它们不会实际的改变数据的类型。

声明变量:

c语言中声明变量是这样的 : 数据类型 变量名=值

还可以 数据类型 变量名; 变量名=值

在c语言中声明变量时的变量名不仅仅表示它后边的值它还表示它的值在内存中的地址,      &变量名       这个&变量就是这个变量的值在内存中的地址。*变量名表示一个存储单元里的数据。

注:字符类型的变量的值要用 '' 包裹并且只能一个字符。c语言中变量可以重新赋值但是不能一个变量声明两次。(在js中的ES5的语法中用var声明的变量可以声明两次且不会报错,在ES6语法中变量不能声明两次否则会报错)

运算符:

运算符基本上和js中的差不多。

  • 基本运算符:

    加法,减法,除法,乘法,取模运算,自增,自减

  • 关系运算符:

    大于,等于,全等,大于等于,非等于

  • 逻辑运算符:

    且,或,非

以上这些运算符和js中的一样进一步了解可参考:https://juejin.cn/post/6844903846808928270#heading-7

输入和输出:

输入和输出分别使用以下这几个函数

  • 输入: scanf()

    这个scanf输入函数基本上跟printf差不多只不过一个是输入一个是输出,它里边也有格式控制符 。 例:scanf("%d\n" , &a) 这个就是输入前边用""包裹是格式控制符,后边的是a是变量 & 是符号,意思是将输入的值赋值给变量a,这个函数是当用户输入完成时会将用户输入的值存进缓存区,当用户按下回车时才会读取


  • 字符以及字符串的输入使用以下这几个函数

    • 单个字符的输入使用:getchar()函数它用于输入单个字符,例:char isd=getchar(),这个函数也是当用户输入完成时会将用户输入的值存进缓存区当用户按下回车时才会读取。

    • 输入字符串用这个函数 : gets() 括号里写你需要将用户输入的值赋值给哪个变量。例: gets(asd) 这个表示将用户输入的值赋值给asd这个变量。虽然scanf()也能用于输入字符串只需写上格式控制符%S即可,但scanf遇到空格时会认为输入结束了,gets会将空格认为字符串的一部分。


  • 输出: printf()

    这个是格式化输出函数,在输出的函数中这个是最常用的,这个printf中格式控制符具体可以查看printf输出函数格式化控制符详解,例: print("%d\n",a) 这个括号里前边用""包裹的就是格式控制符,后边的是变量

判断语句:

c语言中的判断语句基本上和js中的差不多,

c语言中的判断语句大致有以下几种:

当设置判断的条件时就要用到上边的关系运算符,注意:在js中有boolean值ture和false在c语言中没有这个概念在c语言中0为false,非0为true。

  • if else

    例:

    if(条件){

    条件为真时执行这里的代码;

    }else{

    条件为假时执行这里的代码;

    }

  • if else if

    例:if(条件1){
    条件为真时执行这里的代码;

    }else if(条件2){

    当条件1为假时进行下一步判断条件2条件2为真时执行这里的代码;

    }

  • switch

    switch大多用于在多条件判断时

    例: switch(变量){
    case 1 :当变量等于1时执行这里的代码;break;
    case 2 :当变量等于2时执行这里的代码;break;
    case 3 :当变量等于3时执行这里的代码;break;
    case 4 :当变量等于4时执行这里的代码;break;
    case 5 :当变量等于5时执行这里的代码;break; 
    case 6 :当变量等于6时执行这里的代码;break;
    default:当变量不满足以上条件时执行这里的代码;break;

    }

    注:例子里边的变量可以是用户输入的变量 然后case是固定格式 case后边必须是整数或者整数的表达式,break必须写,break的意思是当变量满足某个时执行完代码后讲跳出判断不再继续向下判断,最后的default是可写可不写的default的意思是当变量不满足以上所有条件时将执行default那的代码。

  • 三元运算符,这个也是一种判断语句,主要用于一个条件的判断

    例: 条件?当条件满足时执行这里的代码 : 当条件不满足时执行这里的代码;

循环语句:

c语言中的循环跟js中的循环也几乎都一样。

  • while循环

    例: while(条件){
    当满足条件时执行这里的代码,
      如果条件一直满足会一直执行这里边的代码直至不满足条件将跳出循环

    }

    当条件一直满足时会一直执行代码成为死循环。

  • do{}while()

    例: do{
    要循环执行的代码

    }while(条件)

    do while循环实际与while差不多只有一点不一样,while循环会先判断条件再去执行代码如果条件不满足则不会执行代码,do while循环会先执行一遍代码然后再区进行条件的判断,条件为真则继续执行代码条件为假则不再继续执行代码。

  • for循环

    例:for(语句1;语句2;语句3){要循环的代码;}
    例子中语句1=初始值,语句2=结束条件,语句3=对值的操作 注意:语句之间要用分号分割,最后一个语句3不用分号,语句1只用1次 执行顺序:先执行语句1和语句2判断语句1是否满足结束条件如果满足进入循环体(要循环的代码就是循环体),不满足跳出循环,第一遍执行完之后执行语句3,然后再去执行语句2,判断是否满足条件如果满足进入循环体不满足跳出循环体。循环执行步骤2直至不满足条件退出循环。

    注意:在for循环中如果不带{},比如:for(语句1;语句2;语句3)那么它会将下一条带分号的语句座位循环体。

注:在循环中有一个break关键字用来跳出循环通常跟判断语句结合使用。还有continue关键字是跟if esle 结合使用当continue会跳出当前循环强制进入下一次循环。

数组:

注:在c语言中的数组是静态的也就是说数组不能向数组内部进行增加和删除功能,而在js中数组向数组内部进行增加和删除功能的这种数组叫做动态数组。

我们把一组数据的集合叫做数组,c语言中的数组跟js中的数组略有不同。

数组有以下几种类型:

  • 一维数组

    例 : int a[4];这样就声明了一个整型数组它的长度为4,它的每一个元素都为一个整型。

    数组的赋值方法有以下几种:

    1. 数组类型 数组名 [自定义数组的长度] 数组名[下标]=值
    2. int 数组名[数组的长度]={数组的第一个元素,数组的第二个元素,... ,数组的第N个元素}

    我们通常还通过for循环来为数组赋值。

    注意:声明数组时数组名前面的类型时什么类型那么数组里的每个元素就为什么类型。如果数组中的某个元素未赋值那么他的值默认为0。/p>

  • 二维数组

    可以把二维数组当成一个表格,它有行有列,

    例: 数组类型 数组名[数组中一维数组的长度][数组中二维数组的长度]

    二维数组的赋值:

    数组类型 数组名[一维数组的长度][二维数组的长度]; 数组名[一维数组某个元素的下标][二维数组某个元素的下标]=值;

    也可以通过for循环来为二维数组赋值。

  • 字符数组

    js中有string类型的被称为字符串,而c语言中没有字符串的概念只有单个字符所以在c语言中我们把一串字符串称为字符数组。

    字符数组的定义是这样的:

    char 字符串名 [字符串长度]="这里是你的字符串"

    另外在c语言的字符串中要以\0去进行结尾否则这个字符数组是没有结尾的。

    我们可以引入< string.h >头文件然后利用strlen(字符串名)来求出字符串的长度,另外字符串的长度不包括最后结尾的\0。

    另外输出字符串有两种方式:printf("%s\n",字符串名)和puts(字符串名)

    输入字符串也有两种方式scanf("%s",字符串名)和gets(字符串名)

    输入字符串的这两种方式有一定的区别,通过scanf()输入的字符串遇到空格就会认为字符串结束了而gets()不会。但是scanf()可以指定字符串输入的类型,

    c语言向我们提供了对于字符串的处理函数不过这些函数是包含在string.h的头文件中的我们必须要先引入< string.h >头文件才能使用这几个函数这几个函数分别是以下几个:

    • strcat(x,y)

      strcat(x,y)函数是用来进行字符串拼接的只要我们在strcat的函数里写上两个参数x和y那么y的字符串就会拼接到x字符串的后边,不过前提是x字符串在内存中所占用的空间能够同时存放下x和y两个字符串的空间否则会出现数组越界的问题。

    • strcpy(x,y)

      strcpy(x,y)函数是用来拷贝字符串的只要我们在strcpy(x,y)函数中写上两个参数x和y那么x字符串的内容就会被y字符串的内容覆盖掉。但是前提是x字符串在内存中占用的空间能够存放下y字符串的内容否则就会拷贝的不全面。

    • strcmp(x,y)

      strcpy(x,y)是字符串的比较函数,字符串本身是没有大小的我们对字符串进行比较是比较ascll值从两个字符串的第一个字符开始一一比较如果x字符串跟y字符串相同那么返回0如果x字符串大于y字符串那么返回大于0的值如果x字符串小于y字符串那么返回小于0的值。

数组的越界和溢出:
  • 数组的越界:

    数组中的一项元素都是有它的下标的当我们去访问数组中没有该下标的内容时会发生数组越界的问题,一旦数组越界编译器在编译时就不能进行正常编译还会报给我们一些完全看不懂的报错。

  • 数组的溢出:

    当数组的长度大于我们定义数组时数组的长度时就会产生数组溢出的问题,当我们的数组溢出时编译器在编译时会给我们报错,正常的数组溢出就是在输出数组时多出去的部分会被丢弃但是如果是字符串形式的数组溢出时我们还输出数组时编译器可能会正常通过但是输出的就不是正常的了,所以我们在定义数组和给数组赋值时要细心避免数组溢出的翁提发生。

函数:

其实c语言中的函数也基本上都跟js中的一样但是在c语言中只有一个主函数且只会执行这一个主函数。

在c语言中函数有以下两种:

  1. 第一种是c语言提供给我们的函数,c语言有15个头文件被称为标准库,这些库里边给我们提供了丰富的函数供我们可以去直接去调用。

  2. 第二种是我们自己去定义的一个函数我们在.c文件中可以自己去定义一个函数然后去进行调用。

在c语言中我们都会见到这样的结构

例: int main(){
函数体;
return 0;

}

这个main函数就是c语言的主函数且c语言只会执行这一个主函数,main函数可以去调用其他函数但是却不能它自身却不能被任何函数去调用。我们可以在主函数上方或者主函数内部去自定义函数然后再主函数主区调用自定义函数。

c语言去定义一个函数是这样的,函数类型 函数名(参数){

函数体
return 变量;//这个return时函数在去调用时函数的返回值,在我们去定义函数时函数时什么类型的那么函数的返回值就是什么类型的

}

c语言中函数去调用时这样调用的:

函数名(参数)

另外在c语言中函数也是有作用域的所有在函数内部包括主函数声明的变量都是局部变量,在函数函数外边声明的变量被称为全局变量。

在c语言中函数也有递归递归函数,关=关于递归函数通俗的解释就是在函数内部去调用函数本身。

c语言的预处理命令:

什么是c语言的预处理命令?

在我们去编写.c文件时都会在代码的第一行去写 #include <头文件>。像这种以#开头的命令就叫做预处理命令。我们写的每个.c的文件都是一个可执行程序的源文件,只有我们通过编译器去将我们的.c文件去进行编译的时候才会生成一个可的执行程序。#include是引入头文件的命令一个#include只能引入一个头文件,要引入多个头文件就需要多个#include

宏?

在c语言的预处理命令中有宏的定义,我们可以把宏当作一个定义常量的用法因为我们一旦使用了预处理指令去定义了一个值或者表达式那么我们在下边是无法改变的。宏是通过预处理指令来进行的关于预处理指令指令大致介绍以下几种:

  • #include <头文件>

    这个指令是用来引入头文件的

  • #define 自定义宏名字 字符串或者表达式

    当我们在代码中用到这个自定义宏名时那么这个自定义宏名会被替换成它后边的字符串或者表达式。

    用法:

    #define 宏名(参数) 表达式或值

    调用宏: 宏名(参数)

c语言指针:

在c语言中指针是一个很重要的概念它代表了数据在内存中存储的位置,在js中我们的指针是this。

当我们去声明一个变量名为a的变量时,int a=1; 它的值是存储在内存中的它的变量名a就代表的是这个数据在内存中存储的地址。并且这个变量名并不是真正的地址它只是该数据在内存中存储的地址的一种代称罢了在我们的编译器去编译的时候这些变量名都会被转换成地址然后当我们的编译器去编译时会找到这些变量名代表的地址从而去获取数据。

有了指针我们可以通过 *来定义指针变量不过*号的用法有以下几种:

  • 在运算符中在

    在运算符中*号表示的是乘法

  • 定义指针变量

    当我们去定义指针变量时我们需要在变量名前加上*以表示它是一个指针变量

    例:int *变量名;

  • 给指针变量赋值:

    例: int a=1; int *b=&a;

    &a表示的是变量a在内存中存储的地址。这时我们去输出*b那么它的值就是变量a的数据在内存中所存储的地址。我们也称为b指向了a。

  • 通过指针变量去修改内存中的数据

    例: int a=1; int *b=&a; *b=12;

    我们知道这时候的b指向a,也就是*b代表了a的数据在内存中存储的位置,但是当我们去给*b重新赋值的时候我们是给*b所代表的内存中的地址里的数据修改了修改成为了给*b重新赋值的值。

  • 数组指针:

    我们在定义数组要给出数组名和数组的长度,数组中的每个元素在内存中的地址都是紧挨这个,一整个数组占用的是一整快内存,这时我们的数组名也代表的是一个地址不过它默认的是只代表数组中下标为0的元素所在内存中的地址。

    如果一个指针指向了数据那么我们就称它为数组指针

    例: int arr[10]=[1,2,3,4,5,6,7,8,9]; int *q=arr;

    这时*p代表的是数组arr中的下标为0的元素的地址我们如果想访问下一个元素可以使*p++.在这可能会有疑问为什么在这不适用&arr,因为arr本身代表的就是一个地址了就不需要再去使用&去获取它的地址了。

  • 字符串数组指针:

    上边写了字符串本身就是一种字符数组,只有用定义数组的方式能定义一个数组,但是通过指针我们又引出了一种新的字符串的定义方式。

    例:char zi="yuzhong"; printf("%s",zi);

    我们可以通过指针的方式去定义一个字符串不过这种,这种指针叫做字符串指针,还有就是这种方式声明的字符串称为字符串常量。虽然使用这种定义字符串但是它跟字符串数组上有着本质上的不同:1.这种方式定义的字符串叫做字符串常量它只能去读写但式不能去改变。2。存储方式的不同使用字符串数组存储再全局数据区或者栈区,字符串常量存储再常量区不能进行更改。

什么时候能用到指针变量:(以下只是简单的举了两个例子)

  1. 当做函数参数传递进去,我们我已在在函数将通过指针将我们需要的参数的地址传递进去,以下是一个最简单的例子

    例:int a=1,b=2; int one(int *a,int *b){

    函数体

    } one(&a,&b);

  2. 把数组传递给函数

    我们知道数组是一组数据的集合,它不能一次性的全部传递函数我们可以通过指针将数组传递进去然后对数组进行操作。

使用指针作为函数返回值:

c语言允许函数的返回值是指针我们将这种返回值为指针的函数称为指针函数

二级指针:

在c语言中还有二级指针的定义,什么是二级指针?

我们上边写的那种是叫做一级指针它直接指向某个变量的地址里边的内容。在c语言中我们把*变量名叫做一级指针,**变量名叫做二级指针,***变量名叫做三级指针前边有几个星号就是几级指针

例:
#include <stdio.h>
   int main(){
       int one =10;//这是一个变量one
       int *two=&one;//变量two前边有星号且它的值为&one,&one表示的是变量one的值在内存中的地址然后*two指向这个变量one的地址也就相当于变量two就是one的值
       int **three=&two;//变量three前边有有两个星号且它的值为&two,&two表示的是变量two的值在内存中的地址然后**three指向这个变量two的地址也就相当于变量three就是two的值
       int ***four=&three;//变量four前边有有三个星号且它的值为&three,&three表示的是变量three的值在内存中的地址然后***four指向这个变量three的地址也就相当于变量four就是three的值
       printf("%d",***four); //这里最后输出的是变量one的值。
       return 0; 
   }
空指针:

在js中我们的数据类型中有一种类型叫做null,就是表示为空。注意在js中不要把null和undefinde搞混因为undefinde表示未定义而null表示为空。在c语言中null也表示为空只不过它不是数据类型而是指针,null就是表示空指针。像下面这段代码:

错误的代码:
#include <stdio.h>
   int main(){
       int *one;
       gets(one)
       printf("%d",one);
       return 0;
   }

像这段代码我们就是声明了一个指针变量但是却没有给他赋值,这段代码是错误的但是能编译成功,如果我们使用的是文本编辑器进行编辑的这段代码并且使用了gcc进行编译能编译成功但是输出出的东西确实未知的。如果使用VS进行编译调试那么会给我们报错。

还有就是当我们去声明一个变量时但是未对变量就行赋值却选择输出了这个变量会给我们报错。我们可以在声明变量时给变量赋值为NULL,注意在js中给变量赋值为NULL不区分大小写但是在c语言中NULL一定要是大写。当我们把变量赋值为NULL再进行输出就会输出(null)

void*指针

void* 上边提过void是一个没有类型的也就是类型是不确定的但是void*指针是一个指针它也指向了内存里的某个地址的数据但是内存里的数据类型是不确定的所以我们在使用void*指针时要进行类型转换。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值