美文网首页C语言入门到精通
三天学会C语言编程|下篇

三天学会C语言编程|下篇

作者: SunnyZhang的IT世界 | 来源:发表于2019-03-04 20:02 被阅读0次

    本文是《三天学会C语言编程》的下篇,承接上一篇《三天学会C语言编程|上篇》。本文重点介绍C语言的数据类型、表达式、变量和函数等内容。

    数据类型

    C语言中有多种数据类型,这些数据的类型与我们日常生活中的数据的类型有些类似。比如整型数和浮点型数(小数),还有一些我们平时接触不到的数据类型,如字符串类型(上文中的hello world!就是一个字符串类型的数据)。如下表是C语言支持的数据类型(部分),这里先不用过多理解,只需要知道有这些类型就行,后面会详细介绍。通过这个表可以看出不同类型的数据占用的内存空间大小是不同的

    图1 C语言数据类型列表

    变量

    变量其实是内存的一个区域,用于存储具体的数据,需要说明的是变量是有名称的。变量的名称就好像邮箱的编号一样,这样我们在编程的时候就可以通过这个名字方便的访问(读或者写)变量。

    在C语言中变量的名称可以是英文字符、下划线和数字,但只能以英文字符和下划线开头,不能以数字开头。另外,C语言中变量名称是区分大小写的,也就是var_name和var_Name是两个不同的变量。

    我们知道在C语言中数据是有不同的类型的,同样变量也有不同的类型。不同类型的变量用于存储不同类型的数据,而且不同类型变量占用的空间大小是不同的。那么如何定义一个变量呢?很简单,其基本格式就是类型+变量名称,如下定义了一个整形的变量:

    int var_name;
    

    其它类型的变量与此类似,只是变量的类型不同。至于名称则遵循上文所描述的规范。

    表达式

    我们知道程序最主要的功能就是进行计算的,因此在程序中会有一些表达式进行计算。表达的形式与日常数学中的表达式基本一致,运算的优先级也类似。如下是一个简单的表达式:

    3 + 5 * 6
    

    这个表达式进行简单的数据计算,但该表达式在实际编程时并不没有太大意义,因为计算出的值将被直接丢弃。通常我们需要将表达式计算的值放到一个变量这,这样我们后面才能使用该表达式计算的结果。下面是一个具体的示例:

    #include <stdio.h>
    int main(void)
    {
         int a; //声明整型变量
         long b; // 声明长整型变量
         short c; // 声明短整型变量
         char d; // 声明字符类型的变量
         float e = 1.2; //声明浮点型(小数)变量,在声明的时候可以直接初始化
         int f = 0;
         unsigined int = 3; // 声明无符号整型变量,无符号整形只能是非负整数
         b = 10; //给变量赋值,赋值就是改变变量的内容,让其等于某个值
         c = 11; // 注意赋值的方向,变量在等号左边(又称“左值”),数据在等号右面
         a = a + 10; // 进行基本的加法运算
         c = a + b; /* 可以进行不同类型的变量之间的运算,但可能会丢失数据。因为每种类型变量存储的数值大小是有限的,超过就会溢出。本例中变量c是短整型,范围是-32,768 到 32,767。而变量b是长整形,范围是从-2,147,483,648 到 2,147,483,647。因此,如果计算结果超过了c的范围,将会出现溢出,因此在计算是需要注意。*/
         e = a + b * c; // 这里的*是星号,也就是键盘8上面的字符,代表乘法
         a = (a + e) * c; //可以使用括弧提升运算的优先级,本例中
         a = a /c ; //除法运算
         a = a % c; //取模运算
         a --; //自减运算,也就是自己减1
         a ++; //自加运算
    
         /*除了进行基本的算术运算外,还可以进行位运算。所谓位运算就是逐位运算。*/
    
         a = a & b; //按位“与”运算
         a = a | b; //或
         a = a ^ b; //异或
         a = ~a; //非
         /*关系运算,也就是判断两个或者多个变量的关系。*/
         a == b; //判断两者是否相等,相等返回真,否则返回假
         a >= b; 
         a > b;
         a <=b; 
         a != b; //判断两者是否相等,相等返回假,否则返回真
    
         a && b; //注意是2个&,两者都为真是结果为真。可以多余2个进行运算
         a || b; 
    }
    

    函数

    我们在最一开始的时候已经使用了函数,但还没有对函数进行任何介绍。下面本文将介绍一下什么是函数,为什么要有函数以及函数怎么使用。

    函数是对实现某个功能的代码的封装。有了函数之后,具体的功能我们调用该函数就可以完成,而不同将代码黏贴过来,增加了便利性。

    #include <stdio.h>
    /*下面是函数的定义*/
    int add(int a, int b) /*这一行成为函数头,其中int是函数的返回值类型,add是函数名称,int a和int b是函数的参数(形参)。
    这里返回值和参数可以是任何类型。*/
    { /*函数头后面要紧跟着{,可以与函数头在同一行,或者另起一行,这个代表函数体的开始*/
         int c = 0;
         c = a + b; //这里是函数的具体实现,根其它地方没有任何差异
         return c; //函数的返回值,类型要与在函数头中定义的一直,否则有截断的风险
    }/*函数体的结束*/
    int main(void)
    {
         int a = 0;
    
         a = add(1, 2); /*函数的调用,这里相当于使用add函数的功能,进行加法运算。*/
         printf("result: %d
        ", a);
    }
    

    函数可以与入口函数在相同的文件中,也可以在一个单独的文件中。函数的定义通常在.c文件中,而在头文件(.h文件)中添加声明。这样我们只需要包含头文件就可以使用该函数了。

    控制语句

    通过上面的知识只能写从上往下依次执行的程序。显然这个不能满足实际开发的需求,比如有的时候我们要根据不同的情况执行不同的代码,或者需要重复执行相同的代码等场景。C语言中有多中控制语句,实现对程序不同流程的控制,下面我们以例子的形式进行介绍。

    #include < stdio.h >
    /*这个函数实现成绩的转换,如果大于等于90分则打印“优秀”, 如果在80到90之间,则打印“良好”,如果在70-80之间则打印“中等”, 如果在60到70之间则打印“及格”,否则打印“不及格”。*/
    int print_score(unsigned int score) {
        /* if 是C语言的判断语句,用于判断是否执行后面的代码。
     * 在if关键字后是具体的判断条件表达式,表达式需要
     * 用括弧包括。*/
        if (score > 100) {
            /* 如果条件判断后执行的代码是多行,则需要有{作为执行体的头。 */
            return - 1;
            /*由于成绩不会大于100,因此这里返回-1,表示错误*/
        }
        /* 如果条件判断后执行的代码是多行,则需要有}作为执行体的尾。
     * 如果只有一行代码则不需要{和}两个字符*/
        /* 下面进行分类打印 */
        if (score >= 90) {
            /* 语句块标识符{不一定要另起一行,可以与if在同一行。*/
            printf("优秀
    ");
        } else if (score >= 80) {
            /* 语句 else if 表示另外一种情况。 如果上面符合条件,则不会执行本行。*/
            printf("良好
    ");
        } else if (score >= 70) {
            printf("中等
    ");
        } else if (socore >= 60) {
            printf("中等
    ");
        } else {
            /* else后面可以没有if语句,这样该语句不进行任何判断。如果前面都不满足条件,则到最后执行该语句。*/
            printf("不及格
    ");
        }
    
        return 0; //返回0表示执行成功
    }
    /*上面实现了程序的分支控制,也就是不同的条件执行不同的代码。还有一种情况是需要不断执行某一项重复的计算。这时就需要用到循环语句。
    下面这个函数执行连续整数的累加和,也就是从begin按1递增,一直到end的累加和。比如从5开始一直到9,也就是5 + 6 + 7 + 8 + 9。下面看看如何用循环语句实现这个功能。*/
    int sum(int begin, int end) {
        int index = 0;
        int result = 0;
        /* 循环的关键字是for, 后面()里面的是控制语句。括弧是必须的。括弧内用分号“;”将控制语句分为3部分。第一部分进行初始化,只执行一次;第二部分进行条件判断,每次执行,如果符合条件则执行循环体({}内,这个在单行的情况下可以省略)内的内容,否则跳出循环;最后一个则执行一些额外的运算。上面三部分任何一个都可以为空,三者也可同时为空,但分号不能省略。 */
        for (index = begin; index <= end; index++) {
            /* 这个是开始字符,同判断语句,这里不做过多解释*/
            result = result + index;
        }
        return result;
    }
    /* C语言中还有另外一个关键字实现循环控制,那就是while语句。*/
    int sum2(int begin, int end) {
        int index = 0;
        int result = 0;
        /*想必大家已经找到规律了,while循环也是关键字后面是括弧,然后是循环体。 while语句在括弧中只有一个条件判断,如果满足条件则执行循环体,如果不满足则从循环退出。*/
        index = begin;
        while (index <= end) {
            result = result + begin;
            index++;
        }
    }
    int main(void) {
        int score = 80;
    
        print_score(score);
        sum(1, 5);
        sum2(1, 5);
    }
    

    本文作为入门级教程并没有介绍全部的循环语句,但作为入门已经够用了。后续再详细介绍更多的用法。

    指针

    指针给了我们更大的权限,可以让我们直接操作系统的内存。但是指针也是C语言中最为复杂的部分,也是饱受诟病的部分。只是由于指针的存在使得C语言开发的软件出现问题的复杂度更大,也更难解决。凡事有利有弊,废话少说,我们看看什么是指针。

    简单的理解,指针其实就是内存的地址。由于我们要访问内存,内存肯定要有个编号,这样我们才知道访问哪里的内存。有人可能会说,你不是在前面说通过变量名称进行访问吗?是的,但是变量名称只是在我们编程层面使用内存的方式,真正到操作系统层面都是通过内存的地址进行访问的。

    了解了指针的概念之后,那我们现在谈一下什么是指针变量。我们知道变量是存储数据的,从名称上可以推测出来指针变量就是存储指针的。没错,指针变量就是存储指针的变量,也就是存储内存地址的变量。

    图2 变量与指针变量示意图

    为了便于说明什么是指针及指针变量,我们通过图1进行。假设我们有一个整形变量age,其中的值是0x12345,数据存储在0x1000(这里是为了便于说明,实际位置值的格式大概类似这样,0x7ffc6a95fb14)的位置。

    现在我们想用另外一个变量(比如名称为age_tmp)将该变量的地址保存起来,而且可以通过age_tmp访问age变量中的内容,那该怎么办?没错,就是定义一个指针变量。如图1所示,age_tmp就是这个指针变量,它在0x0800的位置,其内部存储的值是age的地址。好了,废了半天话,那具体怎么编写代码呢?下面我们通过一个例子说明。

    #include < stdio.h > int main(void) {
        int age = 0x12345;
        int * age_tmp;
        /* 这里是定义一个指针类型的变量,仔细看一下在变量名称前有个星号(*),这个代表变量是指针变量。这里定义的是整形指针变量,我们可以定义任何类型的指针变量。通常,某种类型的指针变量只能存储该类型变量的指针(地址)。 */
        age_tmp = &age;
        /*这里是将变量age的地址赋值给指针变量age_tmp,注意看age前面有个与符号(&),这个是取变量地址的意思。*/
        printf("age value: 0x%x
    ", age);
        /*打印变量的值*/
        printf("age address: %p
    ", &age);
        /*打印变量age的地址*/
        printf("age_tmp value: %p
    ", age_tmp);
        /* 打印指针变量的值*/
        printf("age_tmp address: %p
    ", &age_tmp);
        /* 打印指针变量的地址*/
    }
    

    如下是程序执行后的结果,可以看出值的关系与图1是完全一致的。

    age value: 0x12345
    age address: 0x7ffd64adf68c
    age_tmp value: 0x7ffd64adf68c
    age_tmp address: 0x7ffd64adf690
    

    好了,关于指针的相关内容就先介绍到这里,关于指针足够专门写一本书了。

    复合数据类型

    结构体

    C语言最为厉害的地方在于可以支持复合数据类型,所谓复合数据类型就是可以将集中数据类型进行组合封装,形成另外一个新的数据类型。实现这种强大功能的名称叫做结构体,结构体通过struct关键字实现,并用{}界定结构体的内容。下面我们看一个具体的例子。

    #include < stdio.h >
    /*下面是结构体的定义,需要关键字struct,后果是结构体的名字。*/
    struct new_type {
        /*结构体具体内容有左大括弧开始。*/
        int number;
        /*成员变量的第一根我们平时定义变量一样 */
        long age;
        float score;
    };
    /*结构体的具体内容以右大括弧结束,注意后面还有一个分号。*/
    int main(void) {
        struct new_type var_name;
        /* 如何使用新的变量类型,定义方式与普通变量一样,只是需要有struct关键字。 */
        var_name.number = 12;
        /* 对新类型变量成员赋值的方法,中间用点符号(.)连接变量名称和成员名称。 */
        var_name.age = 15;
        var_name.score = 96.5;
        printf("score: %f
    ", var_name.score);
    }
    

    结构体同样也可以有指针类型,本文暂时不做介绍。这部分内容我们后续专门介绍。

    数组

    从名称上也可以看出来,数组是指一组数数组是用来存储一系列数据,而且是一系列相同类型的数据。

    图3 数组变量示意图

    如图2所示,我们假设一个整型的数组变量,名称为new_array,由图可以看出其数据在内存总会依次存放。这样有个有点,我们知道该变量的首地址,就能知道后续其它成员的地址,因此也就可以直接访问。下面我们通过实例解释一下。

    #include < stdio.h > int main(void) {
        int new_array[4];
        /* 数组的定义通过在变量名称后面根一对中括号确定,中括号里面的整数是该数组的大小,也即存储几个成员。*/
    
        printf("first member: %d
    ", new_array[0]);
        /* 数组的访问也是通过在变量名称后面跟一个中括弧,其里面的整数表示要访问哪一个成员,需要注意的是数组的成员是从0开始的,表示第一个成员。另外,这里没有对成员进行初始化就进行访问,因此内容是随机的。 */
        new_array[0] = 1;
        /*成员初始化的方法*/
        new_array[1] = 2;
        printf("first member: %d
    ", new_array[0]);
        /* 初始化后再次访问 */
    }
    

    下面是运行后的结果:

    first member: 4195840
    first member: 2
    

    数组可以是任何类型的上面只是数组的基本用法。数组可以一开始就初始化,也可以结合指针使用。

    总结

    到今天本文就算结束了,学完这些基础知识只能算刚抬起脚迈进门槛,另外一只脚还在外面呢。后面需要学习的内容还多着呢。

    相关文章

      网友评论

        本文标题:三天学会C语言编程|下篇

        本文链接:https://www.haomeiwen.com/subject/sclwuqtx.html