C的追忆(0)——绪论

首先,小编要来讲讲为什么要写追忆篇,编程本就需要日复一日练习,如果长时间手不碰键盘,最厉害的程序员都要从复习语法开始,所以为了让小编在未来忘记c语法的时候快速重拾起c语言的语法,也为了为现在在学习的C语言做个小小的笔记,小编这才下定决心开启这一篇章,所以如果这个篇章对大家有帮助那当然是最好,如果觉得太简略,还留小编一条狗命,毕竟这个只需要小编看懂就行(狗头保命),大家有问题直接评论区留言就好,小编会一一解答。

在这一章我们先来粗略了解一下C语言,更深入的留在后面几章进行讲解。

目录

一. 第一个C语言程序

二. 数据类型

三. 变量、常量

四. 字符串

五. 符号

六. 选择(分支语句)语句

六. 循环语句

七. 函数

八. 数组

九.操作符

十. 常见关键字

十一. define 定义常量和宏

十二. 指针

十三. 结构体


 

一. 第一个C语言程序

#include <stdio.h>
int main()
{
    printf("hello bit\n");
    printf("he he\n");
    return 0;
}

//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个


二. 数据类型

在我们深入理解之前,我们先来看看C语言中有哪些类型(注意:下面的B是字节单位的简称,全称为Byte):
类型含义占据空间大小
   char    字符数据类型1B
  short  短整型2B
int整形4B
long长整型4或8 B(取决于编译器和系统)
long long更长的整形8B
float单精度浮点数4B
double 双精度浮点数8B


三. 变量、常量

生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变得值C语言中用变量来表示。

3.1 变量的分类和定义

常见的变量分为两类:

(1)局部变量
(2)全局变量

定义例程如下:

#include <stdio.h>
int global = 2019;//全局变量
int main()
{
    int local = 2018;//局部变量
    //下面定义的global会不会有问题?
    int global = 2020;//局部变量
    printf("global = %d\n", global);
    return 0;
}

3.2 变量的作用域和生命周期

(1)作用域

作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用

而限定这个名字的可用性的代码范围就是这个名字的作用域。

1. 局部变量的作用域是变量所在的局部范围。
2. 全局变量的作用域是整个工程。
(2)生命周期:

变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。

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

3.3 常量

C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:

        1.字面常量
        2.const 修饰的常变量
        3.#define 定义的标识符常量
        4.枚举常量

例:

#include <stdio.h>
//举例
enum Sex
{
    MALE,
    FEMALE,
    SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量

int main()
{
    //字面常量演示
    3.14;//字面常量
    1000;//字面常量
 
    //const 修饰的常变量
    const float pai = 3.14f;  //这里的pai是const修饰的常变量
    pai = 5.14;//是不能直接修改的!
 
    //#define的标识符常量 演示
    #define MAX 100
    printf("max = %d\n", MAX);
 
    //枚举常量演示
    printf("%d\n", MALE);
    printf("%d\n", FEMALE);
    printf("%d\n", SECRET);
    //注:枚举常量的默认是从0开始,依次向下递增1的
    return 0;
}

注:

上面例子上的 pai 被称为 const 修饰的常变量, const 修饰的常变量在C语言中只是在语法层面限制了变量 pai 不能直接被改变,但是 pai 本质上还是一个变量的,所以叫常变量。


四. 字符串

4.1 字符串

"hello bit.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。

 

五. 符号

5.1 转义字符

转义字符顾名思义就是转变意思,常常用于printf打印函数中,常规方法下无法打印就通过这种方式来打印。

转义字符

释义

\?

在书写连续多个问号时使用,防止他们被解析成三字母词

\'

用于表示字符常量'

\“

用于表示一个字符串内部的双引号

\\

用于表示一个反斜杠,防止它被解释为一个转义序列符。

\a

警告字符,蜂鸣

\b

退格符

\f

进纸符

\n

换行

\r

回车

\t

水平制表符

\v

垂直制表符

\ddd

ddd表示1~3个八进制的数字。 如: \130 X

\xdd

dd表示2个十六进制数字。 如: \x30 0

 

5.2 注释

1. 代码中有不需要的代码可以直接删除,也可以注释掉
2. 代码中有些代码比较难懂,可以加一下注释文字

注释有两种风格:

(1)C语言风格的注释 /*xxxxxx*/
         缺陷:不能嵌套注释


(2)C++风格的注释 //xxxxxxxx
         可以注释一行也可以注释多行

 

六. 选择(分支语句)语句

5.1 if....else

两种结果执行其一,if括号中条件为真执行if,为假执行else。

if(表达式)
{
  语句1;
  ...
}
else{
  语句2;
  ...
}

注意:若多个if...else语句套用,else是和它离的最近的if匹配的。if...else可以不加大括号,但当且仅当跟随执行的语句只有一条时。

 

5.2 switch

本语句也可称为多分支语句,根据给予switch小括号的值,选择大括号内的不同情况进行执行。

switch(整型表达式)
{
   分支项1;
   分支项2;
   分支项3;
   分支项4;
}

以上定义的示例不是很容易理解,我们直接上代码示例:

#include <stdio.h>
int main()
{
      int day = 0;
      scanf("%d",&day);
      switch(day)
     {
        case 1:
          printf("星期一\n");
          break;
        case 2:
          printf("星期二\n");
          break;
        case 3:
          printf("星期三\n");
          break;  
        case 4:
          printf("星期四\n");
          break;  
        case 5:
          printf("星期五\n");
          break;
        case 6:
          printf("星期六\n");
          break;
        case 7:
          printf("星期天\n");  
          break;
        default:
          printf("输入错误");
          
     }
      return 0;
}

(1)case

相当于执行的入口,当给day赋值时,程序会按case后方跟随的入口标志进入该分支开始执行程序。

(2)break

break语句用于提前结束代码块的执行,可以终止循环或switch语句中的一个case。在嵌套循环中,break语句只能跳出最内层循环。

在这里,我要重点说明一下break,由特定case的入口进入分支之后,程序不遇到break,是不会停止执行的,也就是说如果一个分支后面如果没有break,会接着执行下一个分支,直至遇到break为止或switch中剩余所有语句都执行完,default也会被执行,所以case才被我称为入口而非选项。

注意:break是C语言中的一个关键字。

(3)default

这个语句就相当于除了switch中指定的几个case分支情况其余所有情况,该语句可以省略,非必要出现,值得注意的是没有break,其后语句也和正常case后语句一样会被执行。

注意:switch的()中的变量只能使用整形(int)或字符型(char)变量,其余类型都不行。

 

六. 循环语句

有些事必须一直做,比如我日复一日的讲课,比如大家,日复一日的学习,这些要重复执行的就是循环。

前面我们学了if,当条件满足的情况下,if语句后的语句执行,否则不执行。
但是这个语句只会执行一次,为了实现更多次,下面我就来为大家介绍C语言实现循环的三种语句。

6.1 while

while是C语言中的一个循环语句,用于在满足特定条件时重复执行一段代码。

当条件表达式为真(非零)时,循环体内的代码将被执行。每次执行完循环体后,条件表达式会被重新计算,如果仍然为真,则继续执行循环体内的代码。当条件表达式变为假(零)时,循环结束。

//while 语法结构

while(表达式)
{
    循环语句;
    ...
}

使用范例代码:

//在屏幕上打印1-10的数字。

#include <stdio.h>
int main()
{
    int i = 1;
    while(i<=10)
    {
        printf("%d ", i);
        i = i+1;
    }
    return 0;
}

6.1.1 while语句中的break和continue

(1) break

break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的。

(2) continue

continue在while循环中的作用就是:
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,
而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。

注意:continue跳过一次循环,break终止循环,且break可在switch中使用用以终止执行,而continue在switch使用无意义。

 

6.1.1 while循环的执行流程:

72d34c1c28d94998b55942b4204b719c.png

6.2 for

for同样是是C语言中的一个循环语句,用于在满足特定条件时重复执行一段代码。

其基本语法如下:

for (初始化表达式; 条件表达式; 更新表达式) {
    // 需要重复执行的代码块
}

其中,初始化表达式是在进入循环之前执行一次的表达式,用于设置循环变量的初始值条件表达式是一个布尔表达式,用于判断是否继续执行循环体内的代码;更新表达式是在每次循环结束时执行的表达式,用于更新循环变量的值

 

需要注意的是,for循环中的条件表达式更新表达式可以省略,此时循环将一直执行,直到遇到break语句或程序结束。

使用示范:

#include <stdio.h>
int main()
{
    int i = 0;
    //for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
    for(i=1; i<=10; i++)
    {
        printf("%d ", i);
    }
    return 0;
}

6.2.1 break和continue在for循环中

我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。

上方我已介绍过了,这里就不在详述。

6.2.2 for循环的执行流程图:

cd268cf5133148cf92b43a2ab8254c49.png

注意:
        1. 尽量不要在for 循环体内修改循环变量,防止 for 循环失去控制。
        2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。

6.3 do...while

do...while同样是C语言中的一个循环语句,用于在满足特定条件时重复执行一段代码。

其基本语法如下:

do {
    // 需要重复执行的代码块
} while (条件表达式);

6.3.1 do while循环中的break和continue

他们的意义和在while循环中是一样的,上方我已介绍过了,这里就不在详述。

6.3.2 do...while的执行流程图:

0f607bce7b2f440ba778d409267dafc7.png

 

注意:与for和while循环不同的是,do...while循环至少会执行一次循环体内的代码,然后再根据条件表达式判断是否继续执行。如果条件表达式为真(非零),则继续执行循环体内的代码;如果条件表达式为假(零),则跳出循环。

 

七. 函数

这里我们只大致讲一下函数概念,更具体的还是要大家去自己查找和学习,其中奥妙只有自行体悟才行有所收获。

7.1 函数定义

数学中我们常见到函数的概念。但是你了解C语言中的函数吗?

维基百科中对函数的定义:子程序

(1)在计算机科学中,子程序(英语:Subroutine, procedure, function, routine, method,
subprogram, callable unit),是一个大型程序中的某部分代码, 由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代 码,具备相对的独立性。


(2)一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。这些代码通常被集成为软件库。

7.2 函数分类

(1)库函数

库函数是把一些常用到的函数编完放到一个文件里,供不同的人进行调用的一种方式。这些函数一般会被放到lib文件里。在C语言中,库函数的使用非常普遍和重要。例如,ctype、time、stdio、stdlib、math、string等都是常用的库函数。当程序员需要使用某个库函数时,只需要在其源文件中用#include<>指令包含相应的头文件即可,如要使用数学库函数,就需要在代码中加入#include<math.h>。

 以下是一个C语言库函数查找网站,大家可以去学习一下。

cppreference.com

这里我就不在详细叙述。

(2)自定义函数

简单来说,就是自己写的或他人写的非库函数。

7.3 函数的参数

常用的有两类

(1)实际参数(实参):

有确定值

(2)形式参数(形参):

无确定值

7.4 函数调用

(1)传值调用

函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

(2)传址调用

1.传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。


2.这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

7.5 函数的声明和定义

(1)声明

函数要保证先声明后使用

(2)定义

函数的定义是指函数的具体实现,交待函数的功能实现。

7.6函数的嵌套调用和链式访问

函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。

(1)嵌套调用

一个函数中调用另一个函数。

例:

#include <stdio.h>

void new_line()
{
    printf("hehe\n");
}

void three_line()
{
    int i = 0;

    for(i=0; i<3; i++)
     {
         new_line();
     }
}

int main()
{
    three_line();
    return 0;
}

注:函数可以嵌套调用,但是不能嵌套定义。

(2)链式访问

把一个函数的返回值作为另外一个函数的参数。

例:

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[20] = "hello";
    int ret = strlen(strcat(arr,"bit"));//这里介绍一下strlen函数
    printf("%d\n", ret);
    return 0;
}

#include <stdio.h>
int main()
{
    printf("%d", printf("%d", printf("%d", 43)));
    //结果是啥?
    //注:printf函数的返回值是打印在屏幕上字符的个数
    return 0;
}

7.7 函数递归

程序调用自身的编程技巧称为递归( recursion)。

递归的主要思考方式在于:把大事化小

递归的必要条件:

(1) 存在限制条件,当满足这个限制条件的时候,递归便不再继续。
(2) 每次递归调用之后越来越接近这个限制条件。

递归示例:

/*
接受一个整型值(无符号),按照顺序打印它的每一位。
例如:
输入:1234,输出 1 2 3 4
*/

#include <stdio.h>
void print(int n)
{
    if(n>9)
    {
        print(n/10);
    }
    printf("%d ", n%10);
}
    
int main()
{
    int num = 1234;
    print(num);
    return 0;
}


八. 数组

数组是一组相同类型元素的集合。

8.1 一维数组

创建方式:

type_t  arr_name  [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小

例:

int arr1[10];

8.2 二维数组

例:

/数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};//二维数组如果有初始化,行可以省略,列不能省略

8.3 数组使用

例:

for(i=0; i<10; i++)//这里写10,好不好?
{
    arr[i] = i;
}

1. 数组是使用下标来访问的,下标是从0开始。
2. 数组的大小可以通过计算得到。

8.4 数组越界

数组的下标是有范围限制的。


数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

 

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查。


九.操作符

9.1 操作符优先级表:

操作

描述

用法示例

结果类

结合

是否控制求值 顺序

()

聚组

(表达式)

与表达

式同

N/A

()

函数调用

rexp( rexp ,...,rexp)

rexp

L-R

[ ]

下标引用

rexp[rexp]

lexp

L-R

.

访问结构成员

lexp.member_name

lexp

L-R

->

访问结构指针成员

rexp->member_name

lexp

L-R

++

后缀自增

lexp ++

rexp

L-R

--

后缀自减

lexp --

rexp

L-R

!

逻辑反

! rexp

rexp

R-L

~

按位取反

~ rexp

rexp

R-L

+

单目,表示正值

+ rexp

rexp

R-L

-

单目,表示负值

- rexp

rexp

R-L

++

前缀自增

++ lexp

rexp

R-L

--

前缀自减

-- lexp

rexp

R-L

*

间接访问

* rexp

lexp

R-L

&

取地址

& lexp

rexp

R-L

sizeof

取其长度,以字节 表示

sizeof rexp sizeof(类 型)

rexp

R-L

(类

型)

类型转换

(类型) rexp

rexp

R-L

*

乘法

rexp * rexp

rexp

L-R

/

除法

rexp / rexp

rexp

L-R

%

整数取余

rexp % rexp

rexp

L-R

+

加法

rexp + rexp

rexp

L-R

-

减法

rexp - rexp

rexp

L-R

<<

左移位

rexp << rexp

rexp

L-R

>>

右移位

rexp >> rexp

rexp

L-R

>

大于

rexp > rexp

rexp

L-R

>=

大于等于

rexp >= rexp

rexp

L-R

<

小于

rexp < rexp

rexp

L-R

<=

小于等于

rexp <= rexp

rexp

L-R

操作

描述

用法示例

结果类

结合

是否控制求值 顺序

==

等于

rexp == rexp

rexp

L-R

!=

不等于

rexp != rexp

rexp

L-R

&

位与

rexp & rexp

rexp

L-R

^

位异或

rexp ^ rexp

rexp

L-R

|

位或

rexp  | rexp

rexp

L-R

&&

逻辑与

rexp && rexp

rexp

L-R

||

逻辑或

rexp  || rexp

rexp

L-R

? :

条件操作符

rexp? rexp : rexp

rexp

N/A

=

赋值

lexp = rexp

rexp

R-L

+=

以...加

lexp += rexp

rexp

R-L

-=

以...减

lexp -= rexp

rexp

R-L

*=

以...乘

lexp *= rexp

rexp

R-L

/=

以...除

lexp /= rexp

rexp

R-L

%=

以...取模

lexp %= rexp

rexp

R-L

<<=

以...左移

lexp <<= rexp

rexp

R-L

>>=

以...右移

lexp >>= rexp

rexp

R-L

&=

以...与

lexp &= rexp

rexp

R-L

^=

以...异或

lexp ^= rexp

rexp

R-L

|=

以...或

lexp  |= rexp

rexp

R-L

,

逗号

rexp , rexp

rexp

L-R

十. 常见关键字

11.1 常见关键字速览

auto    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

11.2 typedef

类型重命名

11.3 static

static是用来修饰变量和函数的
1. 修饰局部变量-称为静态局部变量
2. 修饰全局变量-称为静态全局变量
3. 修饰函数-称为静态函数


十一. define 定义常量和宏

//define定义标识符常量
#define MAX 1000

//define定义宏
#define ADD(x, y) ((x)+(y))

#include <stdio.h>
......


十二. 指针

指针理解的2个要点:
        1. 指针是内存中一个最小单元的编号,也就是地址
        2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:1.指针就是地址,口语中说的指针通常指的是指针变量
           2.指针是用来存放地址的,地址是唯一标示一块地址空间的。
           3.指针的大小在32位平台是4个字节,在64位平台是8个字节。

12.1 常见指针类型

char  *pc ;
int  *pi ;
short *ps ;
long  *pl ;
float *pf ;
double *pd ;

还有不少像结构体指针,数组指针,二级指针等等我就不在此详细展开。

12.2 指针的操作

(1)指针+- 整数

指针指向地址改变

(2)指针-指针

获得两指针在在地址上相差多少。

(3)指针的关系运算

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。


十三. 结构体

结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。

定义案例例:

struct Stu
{
    char name[20];//名字
    int age;    //年龄
    char sex[5];  //性别
    char id[15]; //学号
};

结构体初始化案例:

/打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};

//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);

//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps-
>id);

到这c语言的知识就算整体的看了一遍,当然,这些讲的还不够细致,只不过给各位大佬回顾一下,作为绪论,任务已经完成的很出色了,更多细节我会在后续篇章中详述。

 

 

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值