【通俗易懂】C语言教程----初识C语言

1.什么是C语言?

C语言是一门通用计算机编程语言,广泛应用于底层开发。

C语言的设计目标是提供一种能以简易 的方式编译、处理低级存储器、产 生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。 尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的 C语言程序可在许多电脑平台上进 行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。

二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制 定了一套完整的美国国家标准语 法,称为ANSI C,作为C语言最初的标准。

目前2011年12月8日,国际标准化组织(ISO)和 国际电工委员会(IEC)发布的C11 标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。

C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。

2. 第一个C语言程序

#include <stdio.h>//引用头文件,使我们可以使用C语言库本身就已经提供给我们的函数,即库函数
int main()//main()是主函数
{
    printf("hello world\n");//printf()是输出函数,'\n'是换行的意思
    return 0;//使程序退出,0的意思是程序正常退出
}
//解释:
//main函数是程序的入口
//一个工程中main函数有且仅有一个

程序执行结果:

3. 数据类型

char //字符数据类型

short //短整型

int //整形

long //长整型

long long //更长的整形

float //单精度浮点数

double //双精度浮点数

//C语言有没有字符串类型?

答案:C语言本身并没有字符串类型,我们在C语言程序中使用的字符串实际上是字符数组,即多个字符构成的就是字符串!

下面是字符串的两种定义方式:

#include<stdio.h>
int main()
{
    char string1[] = "abc";
    char string2[] = { 'a','b','c' };
    return 0;
}

这两种方式的区别并不在此处进行详细的讲解,在后面会进行详细的讲解,此处只是希望大家能够了解即可!

  • 为什么出现这么的类型?

答案:一方面是能够存储更加多样的数据,便于进行数据处理;另一方面的原因就是为了能够更好节约我们的内存空间!至于为什么会这么说呢,后面关于不同数据类型所占的内存空间大小的时候大家能够了解到,并且对其能够有一个更加深入的了解。

  • 每种类型的大小是多少?
#include <stdio.h>
int main()
{
    printf("%d\n", sizeof(char));
    printf("%d\n", sizeof(short));
    printf("%d\n", sizeof(int));
    printf("%d\n", sizeof(long));
    printf("%d\n", sizeof(long long));
    printf("%d\n", sizeof(float));
    printf("%d\n", sizeof(double));
    printf("%d\n", sizeof(long double));
    return 0;
}

下面即为代码的运行结果:

类型的使用:

char ch = 'w';
int weight = 120;
int salary = 20000;

3. 变量、常量

生活中的有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)

有些值是可变的(比如:年龄,体重,薪资)。

不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。

3.1 定义变量的方法

int age = 150;
float weight = 45.5f;
char ch = 'w';

3.2 变量的分类

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

输出结果展示:

总结:

上面的局部变量global变量的定义其实没有什么问题的!

当局部变量和全局变量同名的时候,局部变量优先使用,这就是我们常说的局部优先原则!

3.3 变量的使用

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个操作数:>");
    scanf("%d %d", &num1, &num2);
    sum = num1 + num2;
    printf("sum = %d\n", sum);
    return 0;
}

此处简单带大家了解一下printf()函数和scanf()函数!

printf()函数:输出函数。在双引号内的将进行输出,而%就是控制变量的输出格式,即起到了格式控制的作用,比如%d就是将变量以整型的形式进行打印输出到屏幕上来,%c则是以字符型的形式进行打印输出!在逗号后面的就是我们想要输出的变量,在这个地方需要大家进行注意,%格式控制一定要与后面的变量进行意义对应!

scanf()函数:输入函数。跟上面的一样,%也是进行格式控制,不过此处与前面的区别就是此处是进行输入的格式控制,比如%d,就是将我们的输入的内容以整型的形式存储到我们的变量中,此处与前面也一样,都要与逗号后面的变量进行严格的对应,但此处仍然有一个需要大家进行注意的点,比如我们在输入时,我们在%d %d两个%d中间有一个空格进行分隔,那么我们在通过键盘进行输入的时候也要在两个变量中间进行分隔,即我们的输入要与双引号之间的内容进行严格第对应!

由于本节旨在带大家进行初识C语言,所以不进行过多的讲解!

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

(1)作用域

作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用 的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

  • 1. 局部变量的作用域是变量所在的局部范围。
  • 2. 全局变量的作用域是整个工程。

(2)生命周期

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

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

3.5 常量

C语言中的常量和变量的定义的形式有所差异。

C语言中的常量分为以下以下几种:

  • 字面常量
  • const 修饰的常变量
  • define 定义的标识符常量

  • 枚举常量

const修饰的常变量:

#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. 字符串+转义字符+注释

4.1 字符串

"hello bit.\n"

这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符 串。

注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串 内容。

#include <stdio.h>
//下面代码,打印结果是什么?为什么?(突出'\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;
}

在着我们可以看到,我们在输出arr2时出现了乱码形式,为什么会出现这种情况呢?因为在arr2中并不包含字符串的结束标志即'\0',所以会出现上面的乱码!

注意:

1、在我们用printf()函数以字符串形式进行输出时,只有遇到'\0'才会停止输出!

2、我们在使用上面arr1这种形式进行定义字符串时,在""里面的字符串中就已经自动包含了字符串的结束标志即'\0'!

3、当我们在使用{}字符串的定义的 方式时我们一定要记得加上字符串的结束标志,虽然我们有时候用不到,但这却是我们必须要做的,这也是一个合格的程序员必备的素养,当然,有的时候确实并不需要加上,在新手期间,建议还是加上。

4.2 转义字符

假如我们要在屏幕上打印一个目录: c:\code\test.c

我们该如何写代码?

#include <stdio.h>
int main()
{
    printf("c:\code\test.c\n");
    return 0;
}

但其实打印结果是这样的:

这里就不得不提一下转义字符了。转义字符顾名思义就是转变意思。

下面看一些转义字符。


下面是一个简单的练习:

#include <stdio.h>
int main()
{
    //问题1:在屏幕上打印一个单引号',怎么做?
    //问题2:在屏幕上打印一个字符串,字符串的内容是一个双引号“,怎么做?
    printf("%c\n", '\'');
    printf("%s\n", "\"");
    return 0;
}

下面是一道笔试题,带大家来了解一下吧!

//程序输出什么?
#include <stdio.h>
int main()
{
    printf("%d\n", strlen("abcdef"));
    // \62被解析成一个转义字符
    printf("%d\n", strlen("c:\test\628\test.c"));
    return 0;
}

下面是我们在VS上的运行结果:

为什么会得到上面的结果呢?

我们首先来了解一下strlen(),这个函数的作用是求字符串的长度,当遇到字符串的结束标志时将停止,但是大家需要注意一点,就是字符串的结束标志'\0'本身并不作为字符串长度的一部分。

我们先看上面这一段代码,strlen()括号中的字符串内容为abcdef还有字符串的结束标志'\0',但是由于字符串的结束标志并不作为字符串长度的一部分,所以字符串的长度为6。

接下来我们来看下一段代码,上面我们已经了解了转义字符,此处需要给大家明确一个概念,转义字符被我们看作成是一个字符,即使它的形式是\后面跟了1个或者多个字符,但strlen()函数只把它看成是一个字符。所以为什么我们的编译器给出上面的结果也就不难理解了,在上面的结果也就不难理解了,\t是一个转义字符,\62也是一个转义字符,为什么8不跟着一块呢?因为\后面跟的是八进制,即只包含0到7的数字,不能包含8,所以8不被包含在内!后面还有已给\t也是一个转义字符!最终得出14的结果!

5. 注释

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

比如:

#include <stdio.h>
int Add(int x, int y)
{
    return x + y;
}
/*C语言风格注释
int Sub(int x, int y)
{
    return x-y;
}
*/
int main()
{
    //C++注释风格
    //int a = 10;
    //调用Add函数,完成加法
    printf("%d\n", Add(1, 2));
    return 0;
}

注释有两种风格:

  • C语言风格的注释 /xxxxxx/ 缺陷:不能嵌套注释
  • C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行

6. 选择语句

如果你好好学习,校招时拿一个好offer,走上人生巅峰,你女朋友继续陪在你的身边!

如果你不学习,毕业等于失业,你女朋友跟你分手了!

这就是选择!

#include <stdio.h>
int main()
{
    int coding = 0;
    printf("你会去敲代码吗?(选择1 or 0):>");
    scanf("%d", &coding);
    if (coding == 1)
    {
        printf("坚持,你会有好offer,女朋友陪在身边\n");
    }
    else
    {
        printf("毕业即失业,女朋友跟你分手\n");
    }
    return 0;
}

下面是运行截图:

7. 循环语句

C语言中如何实现循环呢?

  • while语句-讲解
  • for语句(后期讲)
  • do ... while语句(后期讲)
#include <stdio.h>
int main()
{
    int line = 0;
    while (line <= 20000)
    {
        line++;
        printf("我要继续努力敲代码\n");
    }
    if (line > 20000)
        printf("好offer\n");
    return 0;
}

8. 函数

#include <stdio.h>
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个操作数:>");
    scanf("%d %d", &num1, &num2);
    sum = num1 + num2;
    printf("sum = %d\n", sum);
    return 0;
}
上述代码,写成函数如下:
#include <stdio.h>
int Add(int x, int y)
{
    int z = x + y;
    return z;
}
int main()
{
    int num1 = 0;
    int num2 = 0;
    int sum = 0;
    printf("输入两个操作数:>");
    scanf("%d %d", &num1, &num2);
    sum = Add(num1, num2);
    printf("sum = %d\n", sum);
    return 0;
}

函数的特点就是简化代码,代码复用。

9. 数组

要存储1-10的数字,怎么存储?

C语言中给了数组的定义:一组相同类型元素的集合.

9.1 数组定义

int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素

9.2 数组的下标

C语言规定:数组的每个元素都有一个下标,下标是从0开始的。

数组可以通过下标来访问的。

比如:

int arr[10] = {0};
//如果数组10个元素,下标的范围是0-9

9.3 数组的使用

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

运行结果如下图所示:

10. 操作符

算术操作符

  • / 除
  • % 取余

运算符有很多,此处不再一一列举!后面的内容中会讲!

#include<stdio.h>
int main()
{
    int a = 10;
    int b = 5;
    int c = 3;
    printf("%d\n", a + b);
    printf("%d\n", a - b);
    printf("%d\n", a * b);
    printf("%d\n", a / b);
    printf("%d\n", a % c);
    return 0;
}

下面是运行结果:

11. 常见关键字

  • 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.1 关键字 typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名。

比如:

typedef unsigned int uint_32;
int main()
{
    //观察num1和num2,这两个变量的类型是一样的
    unsigned int num1 = 0;
    uint_32 num2 = 0;
    return 0;
}

11.2 关键字static

在C语言中:

static是用来修饰变量和函数的

  1. 修饰局部变量-称为静态局部变量
  2. 修饰全局变量-称为静态全局变量
  3. 修饰函数-称为静态函数

11.2.1 修饰局部变量

//代码1
#include <stdio.h>
void test()
{
    int i = 0;
    i++;
    printf("%d ", i);
}
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        test();
    }
    return 0;
}
//代码2
#include <stdio.h>
void test()
{
    //static修饰局部变量
    static int i = 0;
    i++;
    printf("%d ", i);
}
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        test();
    }
    return 0;
}

代码1运行结果:

代码2运行结果:

结论:

static修饰局部变量改变了变量的生命周期 让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。

11.2.2 修饰全局变量

注:add.c和test.c代表两个不同的源文件

//代码1
//add.c
int g_val = 2018;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0;
}
//代码2
//add.c
static int g_val = 2018;
//test.c
int main()
{
    printf("%d\n", g_val);
    return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误。

结论:

一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。

11.2.3 修饰函数

//代码1
//add.c
int Add(int x, int y)
{
    return c + y;
}
//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0;
}
//代码2
//add.c
static int Add(int x, int y)
{
    return c + y;
}
//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    return 0;
}

代码1正常,代码2在编译的时候会出现连接性错误.

结论:

一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。

12. #define 定义常量和宏

//define定义标识符常量
#define MAX 1000
//define定义宏
#define ADD(x, y) ((x)+(y))
#include <stdio.h>
int main()
{
    int sum = ADD(2, 3);
    printf("sum = %d\n", sum);

    sum = 10 * ADD(2, 3);
    printf("sum = %d\n", sum);

    return 0;
}

运行结果:

13. 指针

13.1 内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的

所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节

为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址

变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。 取出变量地址如下:

#include <stdio.h>
int main()
{
    int num = 10;
    &num;//取出num的地址
       //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)
    printf("%p\n", &num);//打印地址,%p是以地址的形式打印
    return 0;
}

那地址如何存储,需要定义指针变量。

int num = 10;
int *p;//p为一个整形指针变量
p = &num;

指针的使用实例:

#include <stdio.h>
int main()
{
    int num = 10;
    int* p = &num;
    *p = 20;
    return 0;
}

以整形指针举例,可以推广到其他类型,如:

#include <stdio.h>
int main()
{
    char ch = 'w';
    char* pc = &ch;
    *pc = 'q';
    printf("%c\n", ch);
    return 0;
}

13.2 指针变量的大小

#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
    printf("%d\n", sizeof(char*));
    printf("%d\n", sizeof(short*));
    printf("%d\n", sizeof(int*));
    printf("%d\n", sizeof(double*));
    return 0;
}

上述即为32位平台!

上述为64位平台!

结论:指针大小在32位平台是4个字节,64位平台是8个字节。

14. 结构体

结构体是C语言中特别重要的知识点,结构体使得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);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容