zoukankan      html  css  js  c++  java
  • 【C语言核心基础】基本运算、变量、数组、指针、函数、结构体...

    C 语言基础

    // 引入头文件。里面包含了重要的 printf。

    #include <stdio.h>

    // 入口函数。

    // 参数一指输入的参数个数,参数二保存了所有参数。

    // 返回值为 int 类型,一般 0 代表成功,负数代表失败。

    int main(int argc,char* argv[]){

        printf("Hello World! ");

        return 0;  // 代表执行成功。

    }

    ————————

    通过指令的编译与执行:

    MAC 下的编译使用 clang,Linux 下的编译使用 gcc。

    gcc/clang -g -o Hello xxx.c

        ● -g 是 debug 模式,带有调试信息的。

        ● -o 指明输出文件的名字

        ● xxx.c 源代码

    在 MAC 或 Linux 下使用 ./Hello 来执行

    集成环境的运行,后台其实也是这个步骤。

    一、常用基本类型

        short(短整型)、int(整型)、long(长整型)

        float(单精度浮点型,一般情况使用 float。)、double(双精度浮点型,精度高,适用于科学计算等。)

        char(字符)、char*(字符串)

        void(对类型不关心时)

    二、基本运算

    +、-、*、/、%

    int main(int argc,char* argv[])
    
    {
    
        int a = 10;
    
        float b = 12.5;
    
        // 打印结果;a+b=22.500000 (float 类型)
    
        printf("a+b=%f
    ",a+b);
    
        // 打印结果;... , a*b=125.000000 (float 类型)
    
        printf("a+b=%f
    ,a*b=%f
    ",a+b,a*b);
    
        char c = 'a';
    
        // 打印结果;c=f(c 为字符 a,c 加数字可以变为另一个字符,c+1=b,c+2=c,...)
    
        printf("c=%c
    ",c+5);
    
        // 打印结果;c=102(f 的实际编码的值就是 102)
    
        printf("c=%d
    ",c+5);
    
        int d = 10;
    
        int e = d % 6; // 取余
    
        int f = d / 6; // 取商
    
        // 打印结果;e=4,f=1
    
        printf("e=%d
    ,f=%d
    ",e,f);
    
        return 0;  // 代表执行成功。
    
    }

    三、变量与常量

        ● int a = 0; // 变量,可以再赋值。可以不赋值初始值。

    变量在计算机中的物理意义,就是一个寄存器。寄存器是临时存储数据的,它的速度非常快。从内存中取一块数据时,首先存储到寄存器,当改变这个值时,刷新的是寄存器,可擦除。这样可以加快程序的执行速度。

        ● const int len = 265; // 常量,不可改变。需要赋值初始值。

    在编译程序时,程序中设定了一段静态缓冲区,静态缓冲区是受保护的,通过正常途径是不可修改的。但如果知道内存的具体物理地址,也是可以改变的。

    四、数组

    数组是有序的元素序列(C 语言的数组存放的是同一种类型的元素,索引从 0 开始),C 语言中定义数组需要告诉编译器数组的长度。C 语言中数组的定义; char c[2], int arr[10]

    int main(int argc,char* argv[])
    
    {
    
    //    int arr[10];
    
    //    arr[0] = 1;
    
    //    arr[1] = 2;
    
    //    printf("%d,%d
    ",arr[0],arr[1]);
    
        int arr[10] = {1,2,3,};
    
        // 打印结果;1,2,3,0(默认情况下,不赋值的情况下,数组会初始化为 0。)
    
        printf("%d,%d,%d,%d
    ",arr[0],arr[1],arr[2],arr[3]);
    
        float f[2] = {1,2};
    
        // 打印结果;1.000000,2.000000
    
        printf("%f,%f
    ",f[0],f[1]);
    
        return 0;
    
    }

    五、结构体

    // 它是没有保护的概念的(如 private 等)
    
    struct st {
    
        int a; // 成员 a
    
        int b; // 成员 b
    
    };
    // 结构体可以理解为它是一个类
    
    struct st{
    
        int a;
    
        float f;
    
    };
    
    int main(int argc,char* argv[]){
    
        struct st ss;
    
        ss.a = 12;
    
        ss.f = 10.2;
    
        // 打印结果;struct:12, 10.200000
    
        printf("struct:%d, %f
    ",ss.a,ss.f);
    
        return 0;  // 代表执行成功。
    
    }

    六、枚举类型

    枚举可以认为它是一个有限制的整型。一般情况下的使用,是在有一定数值范围的,比如某个属性的取值只能为 1、2、3。

    enum em {
    
        red_color = 0,  // 值为 0,如果值为 1
    
        green_color,    // 值为 1,则值为 2
    
        black_color    // 值为 2,则值为 3
    
    };
    enum em {
    
        red_color = 5,
    
        green_color,
    
        black_color = 10,
    
        yellow_color
    
    };
    
    int main(int argc,char* argv[]){
    
        enum em ee;
    
     
    
        ee = green_color;
    
        // 打印结果;enum:6
    
        printf("enum:%d
    ",ee);
    
        ee = yellow_color;
    
        // 打印结果;enum:11
    
        printf("enum:%d
    ",ee);
    
        return 0;  // 代表执行成功。
    
    }

    七、指针

    指针就是存放内存地址的变量。地址空间内的存的值,在 C 语言中,它除了可以存放普通的数值,还可以存放另一个内存的地址,这个值就是指针,通过这个值就可以访问到其它地址,然后就可以取出这个地址所存放的数据。所以,这个值可以有多重含义,具体跟业务逻辑相关。

    1、指针的作用:

        ● 提升执行效率。

    一般情况下,将字符串传入函数中,函数对字符串进行操作时,它是一个拷贝的过程,函数将字符串拷贝到自己的函数空间存放起来。多次的拷贝会对整个 CPU 造成巨大的浪费。而指针,只需要向函数传递这个字符串所在的地址,函数通过指针访问字符串。

        ● 更强的控制力。

    因为它具有访问地址的能力。像计算机的硬件实际到操作系统层都会有一个对应的映射地址,通过这个地址,C 语言就能访问到硬件设备,并进行控制。C 语言是更底层的语言,它可以访问设备。

    2、指针的操作:

        ● 对指针本身的操作。

    实际就是对地址的操作。比如,当获取某个空间的指针后,可以对这个指针进行加减乘除的操作,对其加一,就指向了下一个空间。

        ● 对所指向的内容操作。

    指针指向某一个内存地址时,可以获取其内容,可以对这个内容进行加减乘除的操作。

    3、指针的定义与使用:

        ● type* var:type 指类型,比如 int、void 等。

    而 * 代表这个变量是一个指针,可以靠近类型 type 写,表示这种类型的指针,关注指针是什么类型的,也可以靠近变量 var 写,表示这个变量是一个指针,而对类型不关注。这两种写法对编译器是没有区别的,但在编写代码时,最好统一风格。

        ● *var:表示获取指针所指向的内容

    4、堆内存的分配与释放:

        ● 分配内存:void* mem = malloc(size);

        ● 释放内存:free(mem);

    #include <stdio.h>
    
    #include <stdlib.h> // malloc() 需要的头文件
    
    int main(int argc,char* argv[]){
    
        // malloc() 一般返回的是 void* 类型。
    
        // malloc() 在 <stdlib.h> 头文件中。
    
        char* p = (char*)malloc(10); // 分配十个字符的空间
    
        *p = 'a';      // 第一个字符的位置
    
        *(p+1) = 'b';  // 第二个字符的位置
    
        // 将内存分配的地址告诉 printf,
    
        // printf 将 p 地址所指向的空间的内容以字符串的形式打印出来。
    
        printf("%s
    ",p); // 打印结果;ab
    
        // 将 p 所指向的空间释放掉
    
        // 系统管理层将内存又还给了堆空间
    
        free(p);
    
        *p = 'd';
    
        // 即使把空间释放掉,但因为仍然掌握此空间的位置,知道 p 的指向。
    
        // 所以即使被释放掉了,还是可以对其操作。
    
        printf("%s
    ",p); // 打印结果;db
    
        // 所以为了不让再访问这个地址,要将其指向 NULL,设置为无效地址。
    
        p = NULL;
    
    //    *p = 'e';  // crash
    
        return 0;
    
    }

    八、常见的内存空间

    ● 栈空间:栈的机制,后进先出。最大的特点是,在 C 语言中写的函数,在函数内所分配的所有变量都是在栈空间分配的,当从函数退出时,从栈空间分配的资源会被自动释放。

    分配的资源是有限的,默认每个函数栈空间的大小是 8兆。

    ● 堆空间:需要明确的使用 malloc() 函数来分配资源,使用完内存后,要通过 free() 函数将资源释放回堆空间,这样别人使用时还能从堆空间分配资源。

    分配的资源几乎可以认为是无限的,适合需要大空间的时候。

    ● 内存映射:像一些动态库一般都是将它直接导入内存映射区,也是一段专门的空间。

    比如将某个文件直接映射到内存中,文件的内容与内存形成映射关系,当改变内存中的值时,会直接在系统内部自动更新到文件中。

    ● Linux 内存地址的划分:4G 32 位系统


     

    0 ~ 0x08048000:这段是受保护空间,我们的进程是不能访问的。

    code:存放的是进程所要执行的代码段。

    堆空间的增长是从下向上,栈空间是从上向下,每次分配空间是向下走的。堆空间与栈空间这样的划分是为了减少冲突。

    共享库,或者叫内存映射区,当想通过内存改变文件时,就可以将文件映射到 mmap 这段空间中。

    ● 内存泄漏:

        ▷ 不断的向系统申请内存。

        ▷ 申请的内存不用,也不释放。

    ● 野指针:占用别人的内存称为野指针。

    九、条件判断与循环

    比较运算:

    >、<、>=、<=、==、!=

    if/else 语句:

    if( a> b){ ​ ... }else{ ​ ... }

    for 语句:

    for(int i =0; i<100; i++){ ​ ... }

    while 语句:

    #include <stdio.h>

    #include <unistd.h>  // usleep() 需要的头文件

    int main(int argc,char* argv[]){

        while (1) {  // 死循环

            printf("while... "); // 一秒钟打印一次

            usleep(1000000); // 微秒

        }

        return 0;

    }

    十、函数

    C 语言中的命名一般以 Linux 的风格,单词与单词用下划线连接,单词一般都是缩写。

    // void 返回类型

    // func 函数名称

    // int a 形参

    void func(int a){

        ... // 函数不能太大,一般不超过 50 行。

    }

    ● 函数指针:指向函数的指针变量。通过 C 语言的函数指针可以实现 C++ 中的多态,就是定义的函数指针既可以指向 a 函数,也可以指向 b 函数,对外层来说,只需要调用这个函数指针就可以了。(多态就是指一个函数可以有不同的含义)

    ● 函数指针的格式:返回值类型 (*指针变量名) ([形参列表]);

    ————————

    int func(int x); // 声明一个函数
    
    int (*f)(int x);  // 声明一个函数指针。返回类型和形参必须与指定的函数一致。
    
    f = func;  // 将 func 函数的首地址赋值给指针 f。然后调用 f 即可。
    
    ————————
    
    #include <stdio.h>
    
    int func(int a){
    
        printf("a=%d
    ",a);
    
        return 0;
    
    }
    
    int func1(int b){
    
        printf("b=%d
    ",b+5);
    
        return 0;
    
    }
    
    int main(int argc,char* argv[]){
    
        int (*f)(int);
    
        // 在 C++ 中这就是多态。
    
        // 对上层来讲,调用的都是 f 这个函数指针,但在底层返回的是不同的结果。
    
        f=func;
    
        f(2);
    
        f=func1;
    
        f(3);
    
        // 打印结果;a=2 b=8
    
        return 0;
    
    }

    十一、文件操作

        ● 文件类型:FILE* file; (FILE* 在 Linux 下叫指针,在 Windows 下叫句柄。)

        ● 打开文件:FILE* fopen(path,mode);

        ● 关闭文件:fclose(FILE*);

    #include <stdio.h>
    
    void createfile(char* filename){
    
        // open/create file
    
        FILE* file = fopen(filename,"w");
    
        if (!file) {
    
            printf("Failed to create file (%s)
    ",filename);
    
            return;
    
        }
    
        // 向创建好的文件内写入内容。
    
        // 参数一指写入的字符串,参数二指字符串中的每一项多大,参数三指一共有几项,参数四指写到哪个文件
    
        size_t len = fwrite("aaaaa", 1, 5, file);
    
        if (len !=5) {
    
            // size_t 使用的打印为 %zu。
    
            printf("Failed to write file,(%zu)",len);
    
            fclose(file);
    
            return;
    
        }
    
        printf("Successed to write file
    ");
    
        fclose(file);
    
        printf("Successed to create file
    ");
    
    }
    
    void read_data(char* filename){
    
        FILE* file = fopen(filename,"r");
    
        if (!file) {
    
            printf("Failed to create file (%s)
    ",filename);
    
            return;
    
        }
    
        // 定义为 1k 大小,并初始化为 0。
    
        char buffer[1024] = {0,};
    
        // 参数:读出的数据存放位置,长度,读多少,从哪读。
    
        size_t len = fread(buffer, 1, 10, file);
    
        if (len <= 0) {
    
            printf("Failed to read file!
    ");
    
            fclose(file);
    
            return;
    
        }
    
        printf("read_data:%s
    ",buffer);
    
        fclose(file);
    
        return;
    
    }
    
    int main(int argc,char* argv[]){
    
        // create file
    
    //    createfile("/Users/jianghouren/Downloads/1.txt");
    
        // read file
    
        read_data("/Users/jianghouren/Downloads/1.txt");
    
        return 0;
    
    }

     

    最后,不管你是转行也好,初学也罢,进阶也可,如果你想学编程~

    【值得关注】我的 C/C++编程学习交流俱乐部!【点击进入】

    问题答疑,学习交流,技术探讨,还有超多编程资源大全,零基础的视频也超棒~

  • 相关阅读:
    listen and translation exercise 52
    中译英20
    listen and translation exercise 51
    中译英19
    listen and translation exercise 49
    PyQt(Python+Qt)学习随笔:QTableView的showGrid属性
    PyQt(Python+Qt)学习随笔:视图中类QAbstractItemView的dragDropOverwriteMode属性
    PyQt(Python+Qt)学习随笔:视图中的dragDropMode属性对dragEnabled和acceptDrops属性的影响
    PyQt(Python+Qt)学习随笔:QAbstractItemView的dragEnabled和dragDropMode属性的关系
    PyQt(Python+Qt)学习随笔:QAbstractItemView的verticalScrollMode和horizontalScrollMode属性
  • 原文地址:https://www.cnblogs.com/huya-edu/p/14339975.html
Copyright © 2011-2022 走看看