一. 第一个C程序

(1)、第一个C程序说明:hello world

配置部署好 vsCode 之后,就可以直接在上面写代码了,新建一个新的C程序文件,向屏幕输出一串字符 “Hello World!”

下面,从整体上来分析一下这个最简单的C语言程序,将这个最简程序的各个部分剖析清楚,明白我们写下的每一个字符的具体含义。

#include <stdio.h>                // 头文件

int main(void)                    // 主函数
{
    printf("Hello, World!\n");    // 标准库函数
    return 0;                     // 关键字
}

注意:C语言程序中,任何符号(包括变量和函数)的使用,都是需要提前声明的。

/*
    说明(必须三合一):
        声明:告诉编译器函数定义和变量定义在哪里
        定义:具体的函数或变量定义实现的地方
        调用:跳到定义的地方,执行具体的函数或变量
    流程:
        遇到调用的函数,编译器先检查一下之前有没有这个声明,有的
        话直接跳到那个函数的定义实现的地方执行

*/


#include <stdio.h>              // stdio.h头文件官方:     在这个头文件中有printf等函数或变量的声明语句,编译器已经知晓

extern int funcA(void);         // 自己写的函数或变量声明: funA这个函数,我们需要提前声明,否则编译器找不到
extern int funcB(void);         // extern告诉编译器,需要对所有工程里面的文件进行扫描后,查看到底有没有这个函数或变量的定义,再运行
extern int num;     

// 主函数
int main(void)
{
    printf("hello world!\n");    // 函数调用1:stdio库提供的函数
    funcA();                     // 函数调用2:自己写的函数
    num = 100;                   // 变量的引用

    int ret = funcB();           // 获取funcB函数的返回值,得知这个函数的运行情况
    printf("ret == %d\n", ret);
    return 0;
}


int num  = 100;                  // 变量定义

// 普通函数1
int funcA(void)                  // 函数定义(实现)
{
    printf("hello funcA\n");
    return 0;
}

// 普通函数2
int funcB(void)
{
    printf("hello funcB\n");
    return 0;
}

图解:

(2). 头文件

#include <stdio.h>
  1. 如果程序用到了系统库函数,那么就需要包含相应的系统头文件来进行声明。
  2. 上述代码中用到了库函数 printf ,而这个函数的声明在头文件 stdio.h 中,因此在该程序中需要包含此头文件。

声明:

  • 概念:对源文件外定义的某个符号进行描述的过程,称为声明
  • 作用:经过声明的符号,编译器才能正确识别和编译,否则编译器不认识,无法判定语法错误
  • 符号:变量、函数等
  • 示例:
    // 声明一个变量符号num
    extern int num;
    
    // 声明一个函数符号funA
    extern int funA(void);
    
    // 注意:前面的extern的关键字是可以不写的,但是我建议初学者一定要加
    
    // 缺少头文件报错提醒        implicit declaration 隐式声明
    main.c: In function ‘main’:
    main.c:4:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
         printf("helloworld\n");
         ^~~~~~
    main.c:4:5: warning: incompatible implicit declaration of built-in function ‘printf’
    main.c:4:5: note: include ‘<stdio.h>’ or provide a declaration of ‘printf’

    (3). 主函数格式

    • 主函数是必须有的,每一个C语言程序有且仅有一个main函数,哪怕是空的。
    • 主函数的名字是固定的,叫 main ,这个函数名不可被挪作他用。
    • 主函数是程序的入口,也就是程序开始运行的地方。
    • 主函数分解如下:
      // int: 返回值类型,代表主函数最终的执行结果是一个整型数据
      // main(void): main是函数名,这个名字不能变
      //             void是函数参数列表,可以省略
      int main(void)
      {
      }
    • 在 Linux 环境下,主函数 main 根据程序最终是否需要接收外部命令行参数,实际上有两个版本:

      // 不接收外部命令行参数的版本 (ubuntu终端的你敲的那些命令)
      int main(void)
      {
          ...
      
      }
      
      // 接收外部命令行参数的版本
      int main(int argc, char const *argv[])  
      {
          ...
      }

(4)、printf函数(标准输出函数 --- 屏幕设备)

        C语言被称为是一种面向过程的模块化语言,所谓的模块,指的是一个个功能明确,各司其职的封装函数,他们就像一块块积木,被合理有机地拼搭起来,形成复杂、健壮的程序。(面试题:什么是面向过程(唱歌、跳舞、吃饭、学习、玩游戏)、什么是面向对象(我唱歌、我跳舞、我吃饭、我学习、我玩游戏) ))

        在这之中,系统标准C语言提供了非常多的"模块",printf函数就是其中之一,它的功能就是:向终端输出一段指定格式的数据

// 向终端输出一段字符串
printf("Hello World!\n");
  • 示例:格式输出控制符
// 格式化输出函数
printf(); 

// 根据需要输出不同格式的数据
printf("%d\n", 100);          // 输出1个整数
printf("%d, %d\n", 100, 200); // 输出2个整数

printf("%f\n", 3.14);         // 输出浮点数
printf("%c\n", 'x');          // 输出字符
printf("%s\n", "abcd");       // 输出字符串

printf("string = %s\n", "abcd"); // 输出字符串
  • 图解:

语法点:

  • 类似 %d、%f 被称为格式控制符
  • 一个格式控制符对应一个数据
  • ‘\n’ 是一个字符,表示回车符,详细参阅 ASCII 码表。
    gec@ubuntu:~$ man ascii
  • 格式控制符:
a.十进制整数:        %d
b.八进制整数:        %o
c.十六进制整数:    %x
d.字符:            %c
e.字符串:            %s
f.单精度浮点数:    %f
g.双精度浮点数:    %lf
h.长双精度浮点数:    %Lf
i.地址:            %p
  • 示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
    int   num      = 100;                                // 定义了一个整形类型的叫num的变量,并给其赋值为100这个数
    char  buf[128] = "shijienameda,woxiangqukankan";     // 定义了一个char型数组,该数组的空间内存为128个字节大小,里面存放了这些个字符
    float f1       = 3.14;                               // 定义了一个float型的叫f1的变量,并给其赋值为3.14

    // 1、没有格式控制符的函数
    printf("hello world!\n");

    // 2、打印十进制数
    printf("十进制数 == %d\n", num);                // 要求打印num这个变量的时候,使用十进制表示

    // 3、打印八进制数
    printf("八进制数 == %o\n", num);                // 要求打印num这个变量的时候,使用八进制表示

    // 4、打印十六进制数
    printf("十六进制数 == %x\n", num);              // 要求打印num这个变量的时候,使用十六进制表示
    
    // 5、打印字符(本质上是一个整型数(1个字节))
    printf("字符 == %c\n", num);                    // 要求打印num这个变量的时候,使用字符表示
    /*
        一开始计算机中没有固定的数据(0101 ....)来表示字符(abcdeef!@#$%^&*)
        所以后面定了一个标准:ASCII表(这个表描述了相关的字符(128个字符),对应的数据就是(0-127))
    */

   // 6、打印字符串
   printf("字符串 == %s\n", buf);                   // 要求打印buf这个变量的时候,使用字符串表示
   /*
        问题:
            如果以字符串形式打印num的值,printf("字符串 == %s\n", num);,会出现一下问题
            warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
   
        原因:
            类型不匹配
   */


   // 7、打印小数(浮点型)
   printf("小数(浮点型) == %f\n", f1);               // 要求打印f1这个变量的时候,使用浮点型来表示


    // 8、打印地址
    printf("num == %p\n", &num);                    // &:取地址符号,意思是获取num这个变量的地址     
    /*
            printf("num == %p\n", num);   
            输出为:0x64(这个是值,不是地址,只不过以十六进制表示出来而已)

            printf("num == %p\n", &num);
            输出为:0x7fff27e25ce8(这个是地址,以十六进制表示)
    
    */
    return 0;
}

(5). return语句

        C语言中的关键字 return 的含义是结束一个函数,并返回某个数据(若有)。而具体到 main 函数中时,由于主函数 main 的结束同时也意味着整个程序的结束,因此在上述 Hello World 程序中 return 后整个程序就退出了

int main(void)
{
    ... ...
    // 一般而言,函数正常退出返回0,非正常退出返回非0
    return 0;
}

        一般而言,程序正常退出时,main函数返回值是0;当程序异常退出时,main函数返回值是非0。

        注意,main函数的返回值是给上一级进程的,因此理论上讲在当前的单进程程序中,main函数的返回值究竟是多少都无所谓,因为根本没有去使用这个返回值,除非在多进程程序中,进程间才需要使用main函数的返回值来传递信息。

二、代码风格规范(建议趋近于ST公司)

(1)、标识符命名规则(变量名、函数名、宏定义等)

1、只能包含数字、字母以及下划线,不能包含其他任何特殊字符
2、只能以字母或者下划线开头
3、不能跟系统已有的关键字重名,也不能够跟本命名空间(namespace)中具有相同作用域的其它标识符重名
4、尽量作用一望便知,做到顾名思义,避免使用无意义的字符
  • 示例代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
    // 一、标识符命名规则(变量名、函数名等)
    // 1、只能包含数字、字母以及下划线,不能包含其他任何特殊字符
    int _give_you_little_color_to_see_see_666 = 100;   // 可以
    // int aaa_111_&&&_**** = 200;                     // 不可以,有特殊字符

    // 2、只能以字母或者下划线开头
    int _______nihao = 100;     // 可以
    int shijie______ = 200;     // 可以
    // int 111____nihao = 300;  // 不可以,数字开头了

    // 3、不能跟系统已有的关键字重名,也不能够跟本命名空间(namespace)中具有相同作用域的其它标识符重名
    // int extern = 100;        // 不可以,跟系统已有的关键字重名了
    int num = 200;              // 可以
    // int num = 300;           // 不可以,不能够跟本命名空间(就是在同一层{}中)中具有相同作用域的其它标识符重名
    
    int tmp  = 400;             // 可以(这个tmp变量的命名空间(作用域):main函数的花括号{}范围内)
    {
        int tmp = 500;          // 凡是被花括号{}括起来的变量,其拥有了另外的命名空间
    }                           // 可以,因为现在这个tmp变量的作用域和上面tmp变量的作用域不同(这个tmp变量的作用域范围在:20行到22行)

    // 4、尽量作用一望便知,做到顾名思义,避免使用无意义的字符
    int a;                      // 可以,但是不建议这么写,因为没有具体含义
    int b;
    // aaa();

    int long_time_no_see;       // 可以,只要能够让人望文生义即可(不管是不是正统英文)(推荐)
    int fanggongnizhenshuai;    // 方工的想法:方工你真帅; 别人的想法:方工的你真衰(拼音会容易出现歧义);
    // 拼音的解决方法(科大讯飞);// fang(1)gong(1)ni(3)zhen(1)shuai(4)

    // 推荐的命名方法(强烈推荐,模仿ST公司的命名)
    // A、函数的命名方法:
    // 1、驼峰命名法:  FangHuiQing       // 面向对象的开发的时候会比较多的去使用
    // 2、下划线命名法:fang_hui_qing     // 面向过程的开发的时候会比较多的去使用
    // 3、二合一法:    FANG_HuiQing      // LED_OpenDev(); LED_CloseDev; LED_CtlDev(); // 前面的命名表示文件(led.c和led.h),后面的名字表示函数的功能作用

    // B、变量名的命名方法:
    // 下划线命名法(小写):int led_num; int led_flag; int led_count;                     // 前面的名字表示哪个文件或者哪个功能的,后面的名字就可以知道这个变量的作用

    // C、宏定义    
    // 下划线命名法(大写):#define LED_ON 1   #define LED_OFF 1                          // 前面的名字表示哪个文件或者哪个功能的,后面的名字就可以知道这个变量的作用

    return 0;
}

(2)、缩进:凡是有代码块的地方都必须缩进,一个花括号{}就代表一个代码块

#include <stdio.h>
#define LED_ON  1
#define LED_OFF 0

// 普通函数
void LED_CtlDev(int led_status)
{
    if(led_status == LED_ON)
        printf("led_on........\n");
    else
        printf("led_off........\n");
}

// 主函数
int main(int argc, char const *argv[])
{
    // 1、for循环
    for (int i = 0; i < 100; i++)
    {
        /* code */  // 这里语句需要缩进
    }

    // 2、while循环
    while (1)
    {
        /* code */  // 这里语句需要缩进
    }
    
    // 3、if判断的时候
    int flag = 0;
    if (flag == 0)
    {
        /* code */  // 这里语句需要缩进
    }
    
    // 4、函数
    LED_CtlDev(LED_ON);
  }

(3)、空格:标点符号后面,一般加空格

#include <stdio.h>

// 主函数
int main(int argc, char const *argv[])
{
    int n1 = 100;
    int n2 = 200;
    int n3 = 300;
    printf("n1 == %d, n2 == %d, n3 == %d\n", n1, n2 , n3);
}

(4)、排版

让代码整体往左移:选择代码块+shift键+tab键
让代码整体往右移:选择代码块+tab键
注释/解除注释:选择代码块+ctrl键+/键

注意:程序是写给人看的,一定要在写程序的时候添加必要的注释,养成良好的编程习惯(潜规则)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐