c语言基础

一、环境搭建

  • 编译器(MinGW)

    • 下载地址:https://osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe
    • 安装中一个注意细节

      需要依次右键标记安装,然后点击Apply Changes

  • IDE(CLion)

    • 下载地址:https://www.jetbrains.com/clion/download/other.html
    • 建议选择2022.1.3版本
      需要atob处理后使用:
      
      R1NTWFpFWjU2Ry1leUpzYVdObGJuTmxTV1FpT2lKSFUxTllXa1ZhTlRaSElpd2liR2xqWlc1elpXVk9ZVzFsSWpvaWMybG5iblZ3SUhOamIyOTBaWElpTENKaGMzTnBaMjVsWlU1aGJXVWlPaUlpTENKaGMzTnBaMjVsWlVWdFlXbHNJam9pSWl3aWJHbGpaVzV6WlZKbGMzUnlhV04wYVc5dUlqb2lJaXdpWTJobFkydERiMjVqZFhKeVpXNTBWWE5sSWpwbVlXeHpaU3dpY0hKdlpIVmpkSE1pT2x0N0ltTnZaR1VpT2lKUVUwa2lMQ0ptWVd4c1ltRmphMFJoZEdVaU9pSXlNREkxTFRBNExUQXhJaXdpY0dGcFpGVndWRzhpT2lJeU1ESTFMVEE0TFRBeElpd2laWGgwWlc1a1pXUWlPblJ5ZFdWOUxIc2lZMjlrWlNJNklsQlRWeUlzSW1aaGJHeGlZV05yUkdGMFpTSTZJakl3TWpVdE1EZ3RNREVpTENKd1lXbGtWWEJVYnlJNklqSXdNalV0TURndE1ERWlMQ0psZUhSbGJtUmxaQ0k2ZEhKMVpYMHNleUpqYjJSbElqb2lVRmRUSWl3aVptRnNiR0poWTJ0RVlYUmxJam9pTWpBeU5TMHdPQzB3TVNJc0luQmhhV1JWY0ZSdklqb2lNakF5TlMwd09DMHdNU0lzSW1WNGRHVnVaR1ZrSWpwMGNuVmxmU3g3SW1OdlpHVWlPaUpEVENJc0ltWmhiR3hpWVdOclJHRjBaU0k2SWpJd01qVXRNRGd0TURFaUxDSndZV2xrVlhCVWJ5STZJakl3TWpVdE1EZ3RNREVpTENKbGVIUmxibVJsWkNJNlptRnNjMlY5TEhzaVkyOWtaU0k2SWxCRFYwMVFJaXdpWm1Gc2JHSmhZMnRFWVhSbElqb2lNakF5TlMwd09DMHdNU0lzSW5CaGFXUlZjRlJ2SWpvaU1qQXlOUzB3T0Mwd01TSXNJbVY0ZEdWdVpHVmtJanAwY25WbGZWMHNJbTFsZEdGa1lYUmhJam9pTURFeU1ESXlNRGt3TWxCVFFVNHdNREF3TURVaUxDSm9ZWE5vSWpvaVZGSkpRVXc2TlRNNU9ERTVNREl5SWl3aVozSmhZMlZRWlhKcGIyUkVZWGx6SWpvM0xDSmhkWFJ2VUhKdmJHOXVaMkYwWldRaU9tWmhiSE5sTENKcGMwRjFkRzlRY205c2IyNW5ZWFJsWkNJNlptRnNjMlY5LWlBVUw5Yzg5aEErb1hnRkFhanNWOVF5Q09Wc0VOSkdrWmlHUXZXN1hLYUpJRDVYdFhieFU0aUJkTVBhaUpFMUI4ZFpKeTI3VnQxV0pqaW4rb1F0blNDNDd0ME1DeDYxdlBPQkdrL0tBdkVCb2k2ZDhtZlA1dTcyOWcwR0h2YTNuUFhzWTMrSWJuc1dtN1NJc0Iwc3l2dHIxVlJtcXQ3dEJLbTJGNmdSbjRaOFNudmtvUXV5cnZ0Wk44anVKQkV6M2hZR0hINGgranBNbkFZalhaME05MldhRDRhSXZ0R2F6cDQxZjQvRnVYVzZJY1NIVHd1YWxXVkh1dlM5NWZ1eHhBd3BieXhQeVlMb20xVWgvbGE2a1k5K3ppM1I1WjFhbU9IRU9DeVpuU29GRGNNZUtGM3loUVU2L0FqWWlUL2ZPZklDTmNhSy9CSFlaMFZGTUk4ek9RQT09LU1JSUVURENDQWpTZ0F3SUJBZ0lCRFRBTkJna3Foa2lHOXcwQkFRc0ZBREFZTVJZd0ZBWURWUVFEREExS1pYUlFjbTltYVd4bElFTkJNQjRYRFRJd01UQXhPVEE1TURVMU0xb1hEVEl5TVRBeU1UQTVNRFUxTTFvd0h6RWRNQnNHQTFVRUF3d1VjSEp2WkRKNUxXWnliMjB0TWpBeU1ERXdNVGt3Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQ1VsYVVGYzF3ZitDZlk5d3pGV0VMMmV1S1E1bnN3cWI1N1Y4UVpHN2Q3Um9SNnJ3WVVJWHNlVE9BRnEyMTBvTUVlKytMQ2p6S0R1cXdEZnN5aGdETlRnWkJQQWFDNHZVVTJveStYUitGcThuQml4V0lzSDY2OEhlT25SSzZSUmhzcjBySnpSQjk1YVozRUFQekJ1UTJxUGFOR20xN3BBWDBSZDZNUFJnanA3NUlXd0k5ZUE2YU1FZFBRRVZON3V5T3RNNXpTc2pvajc5TGJ1MWZqU2hPblFadUpjc1Y4dHFuYXllRmtOenYyTFRPbG9mVS9UYng1MDJSbzA3M2dHam9lUnpOdnJ5bkFQMDNwTDQ4NlAzS0NBeWlOUGhEczJ6OC9DT01yeFJsWlc1bWZ6bzB4c0swZFFHTkgzVW9HLzlSVndIRzRlUzhMRnBNVFI5b2V0SFpCQWdNQkFBR2pnWmt3Z1pZd0NRWURWUjBUQkFJd0FEQWRCZ05WSFE0RUZnUVVKTm9SSXBiMWhVSEFrMGZvTVNOTTlNQ0VBdjh3U0FZRFZSMGpCRUV3UDRBVW81NjJTR2RDRWpaQnZXM2d1YlNnVW91WDhiT2hIS1FhTUJneEZqQVVCZ05WQkFNTURVcGxkRkJ5YjJacGJHVWdRMEdDQ1FEU2JMR0Rzb041NFRBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREFUQUxCZ05WSFE4RUJBTUNCYUF3RFFZSktvWklodmNOQVFFTEJRQURnZ0lCQUJxUm9OR3hBUWN0OWRRVUZLOHhxaGlaYVlQZDMwVGxtQ21TQWFHSjBlQnB2a1ZlcUEyakdZaEFRUnFGaUFsRkM2M0pLdld2UlpPMWlSdVdDRWZVTWtkcVE5VlFQWHppRS9CbHNPSWdyTDZSbEpmdUZjRVo4VEszc3lJZklHUVpOQ3hZaExMVXVldDJIRTZMSllQUTVjMGpINGtEb29ScGNWWjRyQnhOd2RkcGN0VU8ydGU5VVU1L0ZqaGlvWlFzUHZkOTJxT1RzVis4Q3lsMmZ2TmhOS0QxVXU5ZmY1QWtWSVFuNEpVMjNvemRCL1I1b1VsZWJ3YVRFNldaTkJzK1RBL3FQais1L3dlOU5INzFXUkIwaHFVb0xJMkFLS3lpUHcrK0Z0TjRTdTF2c2REbHJBekRqOUlManBqSktBMUltdVZjRzMyOS9XVFlJS3lzWjFDV0szekFUZzlCZUNVUEFWMXBReThUb1hPcStSU1llbjZ3aW5aMk9POTNleUh2Mkl3NWtibjFkcWZCdzFCdVRFMjlWMkZKS2ljSlN1OGlFT3Bmb2Fmd0pJU1htejF3bm5XTDNWLzBOeFR1bGZXc1h1Z09vTGZ2MFpJQlAxeEg5a21mMjJqalEySmlIaFFaUDdaRHNyZVJyT2VJUS9jNHlSOElRdk1MZkMwV0tRcXJIdTVaelhUSDROTzNDd0dXU2xUWTc0a0U5MXpYQjVtd1dBeDFqaWcrVVhZYzJ3NFJrVmh5MC8vbE9tVnlhL1BFZXB1dVRUSTQrVUp3QzdxYlZsaDV6ZmhqOG9UTlVYZ04wQU9jK1EwL1dGUGwxYXc1VlYvVnJPOEZDb0IxNWxGVmxwS2FRMVloK0RWVThrZStydDlUaDBCQ0hYZTB1Wk9FbUgwbk9uSC8wb25E
      View Code
    • 解决中文乱码问题:
      • 按住快捷键Ctrl + shift + alt + /
      • 然后点开弹出的界面中第一项Regestry...
      • 再取消勾选第一个Key(run.process.with.pty)后面的value选项

二、基础语法

  • 分类

    • 字符串
    • 数组
    • 整型相关(short、int、long)
    • 指针
    • 结构体
    • 预处理和头文件
  • 字符串

    • 在C语言中没有字符串。字符数组 来实现字符串(每个字符占1个字节)。
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          // 字符数组 <=> 字符串
          char v1[] = "abc"; 
          // 等价于 char v1[] = {'a', 'b', 'c', '\0'};
          
          char v2[] = {'h', 'e', 'l', 'l', 'o','\0'};
          char v3[] = "def";
      
          // sizeof()方法:用于计算各数据类型或变量所占用字节数,针对字符串,包含末尾的空字符'\0'
          printf("字符串(%s)字节大小:%d\n", v1, sizeof(v1) / sizeof(char)); // 结果:4
      
          // strlen()方法:用于计算一个字符串的长度(不包括字符串末尾的空字符’\0’)
          printf("字符串(%s)长度:%d\n", v1, strlen(v1)); // 结果:3
      
          // strcpy()函数:将一个字符串数组中的值拷贝到另一个字符串数组中,在C语言中,数组是不能直接赋值给另一个数组的。
          char v4[sizeof(v1) / sizeof(char)]; // 定义v4数组,保证大小与v1数组相同
          strcpy(v4, v1); // 使用strcpy()函数将v1的值拷贝到v4中
      
          // strcat()方法:字符串拼接,会修改dest字符串的内容,dest和src字符串必须以空字符('\0')结尾,否则连接的结果可能会不正确。
          strcat(v1, v3);
          printf("字符串(%s)拼接(%s)后结果:%s,长度:%d\n", v4, v3, v1, strlen(v1));
      
          // 字符数组 -> 字符串
          printf("v2值:%s\n", v2);
      }
  • 数组

    • 对于数组来说,内部元素是挨个存放,内存地址相邻。
    • 数组中元素固定、类型固定
    • 数组变量,也是(指向)数组第一个元素的内存地址。
      # include <stdio.h>
      
      int main(int argc, char const *argv[]) {
      
          // 字符数组
          char v1[] = "hello";
      
          // 整型数组(每个整型4字节)
          int v2[] = {11, 22, 33, 44, 55};
      
          printf("v1的值为: %p \n", v1);
          printf("v1的值为: %p \n", &v1);
          printf("v1的值为: %p \n", &v1[0]);
          printf("v1的值为: %p \n", &v1[1]);
      
          printf("----------------------------------------\n");
      
          printf("v2的值为: %p \n", v2);
          printf("v2的值为: %p \n", &v2);
          printf("v2的值为: %p \n", &v2[0]);
          printf("v2的值为: %p \n", &v2[1]);
          return 0;
      }
      
      /*输出结果
      v1的值为: 000000c336bff8ba 
      v1的值为: 000000c336bff8ba 
      v1的值为: 000000c336bff8ba 
      v1的值为: 000000c336bff8bb 
      ----------------------------------------
      v2的值为: 000000c336bff8a0 
      v2的值为: 000000c336bff8a0 
      v2的值为: 000000c336bff8a0 
      v2的值为: 000000c336bff8a4 
       */
  • 整型相关

    • short :2字节
    • int :4字节
    • long:(通常为4字节或8字节,与平台相关,因系统而异)
      # include <stdio.h>
      
      int main(int argc, char const *argv[]) {
      
          // 字符数组
          // signed short v1[] = {11, 22, 33};  //默认是有符号类型
          // unsigned short v1[] = {11, 22, 33};
      
          short v1[] = {-11, 22, 33};
          int v2[] = {11, 22, 33};
          long v3[] = {111,222,333};
          printf("short值:%d,内存地址:%p\n", v1[0], &v1[0]);
          printf("short值:%d,内存地址:%p\n", v1[1], &v1[1]);
          
          printf("----------------------\n");
          printf("int值:%d,内存地址:%p\n", v2[0], &v2[0]);
          printf("int值:%d,内存地址:%p\n", v2[1], &v2[1]);
      
          printf("----------------------\n");
          printf("long值:%d,内存地址:%p\n", v3[0], &v3[0]);
          printf("long值:%d,内存地址:%p\n", v3[1], &v3[1]); // 相邻地址差值是4,
          return 0;
      }
      
      /*
          short值:-11,内存地址:0000009e389ffcfa
          short值:22,内存地址:0000009e389ffcfc
          ----------------------
          int值:11,内存地址:0000009e389ffcec
          int值:22,内存地址:0000009e389ffcf0
          ----------------------
          long值:111,内存地址:0000009e389ffce0
          long值:222,内存地址:0000009e389ffce4
       */
  • 指针

    • 本质上是一种数据类型,用于表示某种数据的内存地址,可以实现让多个变量指向同一个值
    • 两个关键字符:
      • &
        • &变量:获取变量指向数据的内存地址
      • *
        • 放在定义变量前:表示指向这个类型的指针【比如:int *v2 = &v1;】
        • 放在指针类型变量前:表示解引用,即获取内存地址中存储的
    • 一个指针占8字节
      # include <stdio.h>
      
      int main(int argc, char const *argv[]) {
          int v1[] = {11, 22, 33};
          int *p1 = v1; // 等价于&v1、&v1[0]
          printf("指针类型占据字节大小:%d\n", sizeof(p1));
          printf("指针指向的内存地址:%p,存储的数据:%d,指针自身内存地址:%p \n", p1, *p1, &p1);
          p1 += 1;
          printf("指针指向的内存地址:%p,存储的数据:%d,指针自身内存地址:%p \n", p1, *p1, &p1);
          
          char v2[20];
          char *p2 = v2;
          /*
           sprintf函数是C语言中的一个字符串格式化输出函数,用于将数据按照指定的格式输出到字符串中
              参数1:是存放格式化输出结果的字符串的指针
              参数2:格式化字符串
              后面是可变参数
           */
      
          sprintf(p2, "%c", 'h');
          p2 += 1;
          sprintf(p2, "%c", 'e');
          p2 += 1;
          sprintf(p2, "%c", 'l');
          p2 += 1;
          sprintf(p2, "%c", 'l');
          p2 += 1;
          sprintf(p2, "%c", 'o');
          p2 += 1;
          sprintf(p2, "%c", '\0');
          printf("依次添加单个字符后,格式化输出结果:%s \n", v2);
      
          char v3[50];
          int num = 123;
          float f = 3.14;
          sprintf(v3, "数字:%d,浮点数:%f\n", num, f);
          printf("一次性格式化输出结果:%s\n", v3);
          
          return 0;
      }
      
      /*
          指针类型占据字节大小:8
          指针指向的内存地址:00000001001ffd24,存储的数据:11,指针自身内存地址:00000001001ffd18 
          指针指向的内存地址:00000001001ffd28,存储的数据:22,指针自身内存地址:00000001001ffd18 
          依次添加单个字符后,格式化输出结果:hello 
          一次性格式化输出结果:数字:123,浮点数:3.140000
       */
    • 示例:通过指针修改字符串的值
      #include <stdio.h>
      
      int main() {
          char v[] = "hello";
          char *pp = v;
          // 修改字符串的值,等价于后面的操作
          // pp[0] = 'a';
          // pp[3] = 'b';
      
          *pp = 'a';
          pp += 3;
          *pp = 'b';
      
          printf("%s", v); // aelbo
          return 0;
      }
  • 指针的指针

    • 一个指针,内部存储了另一个指针的内存地址
      # include <stdio.h>
      
      int main(int argc, char const *argv[]) {
          int v1 = 100;
          int *p1 = &v1;
          int **p2 = &p1;
          int ***p3 = &p2;
          printf("p1:%d,p2:%d,p3:%d \n", *p1, **p2, ***p3); // p1:100,p2:100,p3:100
      
          // 修改v1变量的值,其它变量取值均随之改变
          v1 = 200;
          printf("p1:%d,p2:%d,p3:%d \n", *p1, **p2, ***p3); // p1:200,p2:200,p3:200
          return 0;
      }

      定义指针的指针时,在前面添加*,同理依次添加*;取指针指向的内存地址中存取的数据时,根据变量前面几个*,采用相同数量的*即可

  • 结构体

    • 结构体用于将不同的数据类型组合在一起形成一个新的数据类型。
    • 定义:
      结构体的定义可以按照以下格式进行:
      
      struct 结构体名 {
         数据类型 成员变量1;
         数据类型 成员变量2;
         // 可以继续添加其他成员变量
      };
      在这个定义中,struct关键字用于声明一个结构体,后面跟着结构体的名称。花括号内是结构体的成员变量,每个成员变量都由数据类型和变量名组成,用分号分隔。
      
      以下是一个结构体的示例定义:
      struct Person {
         char name[50];
         int age;
         float height;
      };
      在这个示例中,Person是结构体的名称,它包含了一个字符数组成员变量name,一个整型成员变量age,以及一个浮点型成员变量height。
    • 示例

      #include <stdio.h>
      
      // 定义结构体
      struct Person {
          char name[30];
          int age;
          float height;
      };
      
      int main() {
          struct Person v1 = {"eliwang", 28, 1.80};
          printf("%s身高:%.2f \n", v1.name, v1.height);
      
          struct Person *pp = &v1;  // pp是一个变量,他是一个指针类型。 *pp
      
          printf("%s年龄:%d岁 \n", (*pp).name, (*pp).age);
          printf("%s年龄:%d岁 \n", pp->name, pp->age); // 上述的一种简写方式,对于指向结构体的指针,使用箭头运算符->可以直接访问结构体成员
      
          return 0;
      }
      /*
          eliwang身高:1.80 
          eliwang年龄:28岁 
          eliwang年龄:28岁 
       */
    • 单向链表实现
      struct Node{
          int data;
          struct Node *next;
      }
      
      struct Node v3 = {33};
      struct Node v2 = {22, &v3};
      struct Node v1 = {11, &v2};
      
      
      v1.data;                // 11
      v1.next->data;           // 22
      v1.next->next->data;    // 33
  • 预处理和头文件

    • 预处理
      • 在程序运行之前会先运行
        • # include <stdio.h>
          
          # define ME  100
          # define SIZE  18
          # define ADD(x1, x2)(x1+x2+100)
          # define DB(x1, x2)(x1*x2)
          
          int main() {
              int data = 19;
              printf("%d-%d-%d \n", ME, SIZE, data); // 100-18-19
              printf("ADD执行结果:%d \n", ADD(20, 40)); // 20 + 40 + 100 = 160
              printf("DB执行结果:%d \n", DB(2 + 3, 40)); // 2 + 3 * 40 = 122,并不会先计算传入的参数结果,而是整体进行替换操作
              return 0;
          }
    • 头文件
      • 头文件的作用是声明函数、变量和数据类型的原型,以便在其他源文件中使用。
      • 头文件通常包含函数和变量的声明,而不包含实际的函数定义。
      • 使用#include<xxx.h>方式引用的是标准库的头文件,而使用#include “xxx.h”方式引用的是自定义的头文件或者项目内的头文件。
        // 项目目录
        ├── main.c
        ├── utils.c
        └── utils.h
        
        
        // utils.h
        int plus(int v1);
        
        
        // utils.c
        int plus(int v1){
            return v1 + 100;
        }
        
        
        // main.c
        # include <stdio.h>
        # include "utils.h"
        
        int main() {
            int data = plus(100);
            printf("结果:%d \n", data);
            return 0;
        }
 
posted @ 2023-09-22 02:46  eliwang  阅读(100)  评论(0编辑  收藏  举报