C语言 - 介绍

printf()标准格式:

  • printf(格式控制字符串,输出列表);
  • "格式控制字符串"是用双引号括起来的一个字符串。包括:
    • 普通字符:普通字符即需要在输出时原样输出的字符。
    • 占位符:由“%”和格式字符组成。这个位置可以用其它值代入。
  • "输出列表"是程序需要输出的一些数据,可以是常量、变量或表达式。用于替换占位符的位置。
  • **注意:**printf() 参数与占位符是一一对应关系。如果参数个数少于对应的占位符, printf() 可能会输出内存中的任意值。

占位符:

  1. 占位符的第一个字符是 % ,第二个字符表示占位符的类型。
  2. printf() 的占位符有许多种类,与 C 语言的数据类型相对应。
  3. %c :char型数据
  4. %d :十进制整数(int)(%i)
  5. %f :浮点数(float)
  6. %ld :十进制整数(long)
  7. %lf :十进制浮点数(double)
  8. %p :指针
  9. %s :字符串
  10. %u :十进制无符号整数(unsigned int)

输出宽度限定:

1
2
printf("%5d\n", 123); // 输出为 "  123" 
printf("%-5d\n", 123); // 输出为 "123 "
  • 说明:%5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
  • 输出的值默认是右对齐,即输出内容前面会有空格;如果希望改成左对齐,在输出内容后面添加空格,可以在占位符的 % 的后面插入一个 - 号。
1
printf("%12f\n", 123.45); // 输出 "  123.450000"
  • 对于小数,这个限定符会限制所有数字的最小显示宽度
  • **注意:**小数点也会占一位
  • %12f 表示输出的浮点数最少要占据12位。由于小数的默认显示精度是小数点后6位,所以123.45 输出结果的头部会添加2个空格。
1
2
printf("%.2f\n", 0.8); // 输出0.80
printf("%6.2f\n", 0.8); // 输出为 " 0.80"
  • %.2f 表示输出字符串最小宽度不限,小数位数为2
  • %6.2f 表示输出字符串最小宽度为6,小数位数为2。整体长度不足 6 位时,前面补空格,而且小数点也会占一位

关键字:

  • 定义:被C语言赋予了特殊含义,用做专门用途的字符串(或单词)。
  • 特点:全部关键字都是小写字母

标识符:

  1. 定义:C语言中变量、函数、数组名、结构体等要素命名时使用的字符序列。
  2. **技巧:**凡是自己可以起名字的地方都叫标识符。
  3. 命名规则:
    • 只能由26个英文字母大小写,0-9 或 _ 组成
    • 数字不可以开头
    • 不可以是关键字,但可以包含关键字
    • C99和C11允许使用更长的标识符名,但是编译器只识别前63个字符。(会忽略超出的字符)
    • 不允许有空格。
    • 严格区分大小写字母。比如:Hello、hello是不同的标识符。

转义字符:

转义字符

变量的作用域:

  • 变量的作用域:其定义所在的一对{ }内有效。
  • 变量只有在其作用域内才有效。出了作用域,变量不可以再被调用。
  • 同一个作用域内,不能定义重名的变量。
  • C 语言的变量作用域主要有两种:文件作用域(file scope)和块作用域(block scope)。
  • **文件作用域(file scope)**指的是,在源码文件顶层声明的变量,从声明的位置到文件结束都有效。
1
2
3
4
5
int x = 1;
int main() {
printf("%d\n", x);
return 0;
}
  • **块作用域(block scope)**指的是由大括号( {} )组成的代码块,它形成一个单独的作用域。凡是在块作用域里面声明的变量,只在当前代码块有效,代码块外部不可见。
1
2
3
4
5
6
7
8
9
10
11
int main() {
int m = 10;
if (m == 10) {
int n = 20;
printf("%d %d\n", m, n); // 10 20
}
printf("%d\n", m); // 10
printf("%d\n", n); // 超出作用域,报错

return 0;
}

变量按类型的分类:

  1. 基本数据类型
  2. 构造类型
  3. 指针类型
  4. 空类型(void)

**注意1:**这里列举的是C语言的常用类型,后续C语言版本还有新增的类型。

**注意2:**空类型:void 表示空类型(无类型)。通常应用于函数的返回值类型、函数的参数、指针类型。

**注意3:**在C语言中,没有字符串类型,使用字符数组表示字符串。

基本数据类型:

  1. 整数类型:

    C语言规定了如下的几类整型:短整型(short)、整型(int)、长整型(long)、更长的整型(long long)

    每种类型都可以被 signed 和unsigned 修饰。

    • 使用 signed 修饰,表示该类型的变量是带符号位的,有正负号,可以表示负值。默认是signed
    • 使用 unsigned 修饰,表示该类型的变量是不带符号位的,没有正负号,只能表示零和正整数。

    bit(位):计算机中的最小存储单位。

    byte(字节):计算机中基本存储单元。

    1byte = 8bit

    整数类型

    关于后缀:

    编译器将一个整数字面量指定为 int 类型,但是如果希望将其指定为 long 类型,需要在该字面量末尾加上后缀 lL ,编译器会把这个字面量的类型指定为 long 。

    1
    long x = 123L; //或者写成 123l

    如果希望字面量指定为long long类型,则后缀以llLL结尾。

    1
    long long y = 123LL;

    如果希望指定为无符号整数 unsigned int ,可以使用后缀 uU

    1
    unsigned int x = 123U;

    L 和 U 可以结合使用,表示 unsigned long 类型。 L 和 U 的大小写和组合顺序无所谓。

    u 还可以与其他整数后缀结合,放在前面或后面都可以,比如 10UL 、 10ULL 和 10LLU 都是合法的。

    1
    2
    unsigned long int x = 1234UL;
    unsigned long long int x = 1234ULL;
  2. 浮点类型:

    • 浮点型变量,也称为实型变量,用来存储小数数值的。

    • 在C语言中,浮点型变量分为三种:单精度浮点型(float)、双精度浮点型(double)、长双精度浮点型(long double)。

      浮点类型

    • 浮点型变量不能使用signed或unsigned修饰符。

    • 最常用的浮点类型为:double 类型,因为精度比float高。

    • 浮点型常量,默认为 double 类型。

    • 关于后缀:

      对于浮点数,编译器默认指定为 double 类型,如果希望指定为float类型,需要在小数后面添加后缀 fF;如果希望指定为long double类型,需要在小数后面添加后缀 lL

      1
      2
      3
      4
      float f = 123.4f;  //后面必须加上字母f或F
      double d1 = 101.1; //后面可以省略字母d
      double d2 = 299.4;  //后面可以加上字母d
      long double x = 3.14L;//后面必须加上字母l或L
  3. 字符类型:

    • C语言中,使用 char 关键字来表示字符型,用于存储一个单一字符
    • 字符型变量赋值时,需要用一对英文半角格式的单引号('')把字符括起来。
    • 占一个字节
  4. 布尔类型:

    • 只有两个值真和假

变量间的转换规则:

  1. 隐式类型转换:(自动类型转换)

    1. 系统自动将字节宽度较小的类型转换为字节宽度较大的数据类型,它是由系统自动转换完成的

    隐式转换

    • **注意:**最好避免无符号整数与有符号整数的混合运算。因为这时 C 语言会自动将 signed int 转为unsigned int ,可能不会得到预期的结果。
  2. 强制类型转换:(显示类型转换)

    • 形式: (类型名称)(变量、常量或表达式)
    1
    2
    double a=2.5;
    int i=(int)a;
    • 功能:将“变量、常量或表达式”的运算结果强制转换为“类型名称”所表示的数据类型。
    • 注意:强制类型转换会导致精度损失。
  3. **注意:**无论是隐式类型转换,还是强制类型转换,都是为了本次执行程序的需要,并不会改变原来的类型和值

  4. 运算的溢出问题:每一种数据类型都有数值范围,如果存放的数值超出了这个范围(小于最小值或大于最大值),需要更多的二进制位存储,就会发生溢出。大于最大值,叫做**向上溢出(overflow);小于最小值,叫做向下溢出**(underflow)

常量:

  1. 程序运行时,其值不能改变的量,即为常量

  2. 字面常量:

    • 2、12是整型常量,2.1、12.5、3.14是实型常量,’a’、 ‘b’、’c’是字符型常量
  3. #define 定义的标识符常量:

    • 在文件开头用 #define 来定义常量,也叫作“宏定义”。所谓宏定义,就是用一个标识符来表示一个常量值,如果在后面的代码中出现了该标识符,那么编译时就全部替换成指定的常量值。即用宏体替换所有宏名,简称宏替换

    • 定义格式:#define 符号常量名 常量值

      • 符号常量名,称为宏体,属于标识符,一般定义时用大写字母表示。

      • 常量值,称为宏名,可以是数值常量,也可以是字符常量。

      • 习惯上,宏名用大写字母表示,以便于与变量区别。但也允许用小写字母。

        1
        2
        3
        4
        5
        6
        7
        #include <stdio.h>

        #define ZERO 0 //#define的标识符常量
        int main() {
        printf("zero = %d\n", ZERO);//结果输出0
        return 0;
        }
    • 跟#include一样,“#”开头的语句都是“预处理语句”,在编译之前,预处理器会查找程序中所有的“ZERO”,并把它替换成0,这个过程称为预编译处理

    • 然后将预处理的结果和源程序一起再进行通常的编译处理,以得到目标代码 (OBJ文件)。

  4. 使用const限定符:

    1. 这种方式跟定义一个变量是一样的,只需要在变量的数据类型前再加上一个const关键字,这被称为“限定符”。
    2. 格式:const 数据类型 常量名 =常量值;
    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>

    int main(){
    //const 修饰的常变量
    const float PI = 3.14f;
    //PI = 5.14;//是不能直接修改的!
    return 0;
    }
    • const修饰的对象一旦创建就不能改变,所以必须初始化。
    • 跟使用 #define定义宏常量相比,const定义的常量有详细的数据类型,而且会在编译阶段进行安全检查,在运行时才完成替换,所以会更加安全和方便。
  5. 定义枚举常量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>

    //使用enum定义枚举类
    enum Sex{
    //括号中的MALE,FEMALE,SECRET是枚举常量
    MALE,
    FEMALE,
    SECRET
    };

    int main(){
    //枚举常量
    printf("%d\n", MALE);
    printf("%d\n", FEMALE);
    printf("%d\n", SECRET);
    //注:枚举常量默认是从0开始,依次向下递增1的
    return 0;
    }

输入和输出函数:

  1. 输出:从计算机向外部输出设备(显示器、打印机)输出数据。

  2. 输入:从输入设备(键盘、鼠标、扫描仪)向计算机输入数据。

  3. 输入函数:scanf() 、 getchar()、gets():

    • scanf(),是格式输入函数,可接收任意类型的数据。
    • getchar(),是字符输入函数, 只能接收单个字符
    • gets(),是字符串输入函数。
  4. 输出函数:printf() 、 putchar()、puts():

    • printf(),是格式输出函数,可按指定的格式显示任意类型的数据。
    • putchar(),字符显示函数,只能显示单个字符
    • puts(),是字符串输出函数。
  5. scanf()的使用:

    • 作用:把从键盘上输入的数据根据找到的地址存入内存中,即给变量赋值。

    • 格式: scanf("格式控制字符串",参数地址列表);

      • “格式控制字符串”:约定输入数据的类型和格式,参数的个数必须与变量地址的个数一致。
      • “参数地址列表”:以逗号 “, ”分隔的、输入数据变量地址序列。
      1
      scanf("%d%d%d",&a,&b,&c)
    • 其中,&a,&b,&c中的&是寻址操作符,&a表示对象a在内存中的地址。

    • 注意:

    • 如果scanf中%d是连着写的,如“%d%d%d”,在输入数据时,数据之间不可以用逗号分隔,只能用空白字符(空格或tab键或者回车键)分隔。即“2(空格)3(tab)4” 或 “2(tab)3(回车)4”等。

    • 如果是“%d,%d,%d”,则在输入数据时需要加“,”,如“2,3,4”。

  6. getchar()与putchar()的使用:

    1. getchar():输入字符数据

      • 格式:getchar()
      • 功能:从键盘缓冲区读入一个字符
    2. putchar():输出字符

      • 格式: putchar(ch);其中ch是一个字符变量
      • 功能:从标准输出设备输出一个字符
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      #include <stdio.h>

      int main() {
      char c = 0;
      putchar('A'); //输出单个字符A
      putchar(c); //输出变量c的ASCII对应字符
      putchar('\n'); //执行换行效果,屏幕不显示
      }


      #include <stdio.h>

      int main() {
      char ch;
      ch = getchar();//从键盘得到一个字符给ch
      putchar(ch);//输出ch
      return 0;
      }
  7. gets()与puts()使用:

    1. puts() 是一个用于输出字符串的标准库函数,其原型定义在 <stdio.h> 头文件中。puts() 函数的作用是将一个以 null 字符(\0)结尾的字符串打印到标准输出(通常是控制台)上,并自动添加一个换行符。

    2. **注意:**puts()函数只能用于输出字符串,而不能输出其他类型的数据。如果需要输出其他类型的数据,应使用 printf() 函数。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      int main() {

      char str1[]={"China\nBeijing"};
      char str2[] = "helloworld";

      puts(str1);

      puts(str2);

      return 0;
      }
    3. gets()读取标准输入设备输入的字符串,直到遇到【Enter】键才结束

      1
      2
      char str[20];   //定义一个数组
      gets(str); //获取输入的字符串,存放到字符数组中
    4. 举例:字符串的读写

      1
      2
      3
      4
      5
      6
      7
      8
      int main() {

      char str[15];
      gets(str); //输入字符串至数组变量str
      puts(str); //输出字符串

      return 0;
      }

局部变量和全局变量:

  1. 局部变量:
    • 函数体内定义的变量,也称内部变量。局部变量只能在定义它的函数中使用。
  2. 全局变量:
    • 函数之外定义的变量称为外部变量,外部变量是全局变量(也称全程变量)。
    • 一个程序中,凡是在全局变量之后定义的函数,都可以使用在其之前定义的全局变量。
  3. 当局部变量和全局变量同名的时候,采用就近原则
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int global = 2023;//全局变量
int main(){
int local = 2022;//局部变量

int global = 2024;//局部变量
printf("global = %d\n", global);//2024
return 0;
}

参考链接: