跳至主要內容

C 语言基础

zedo2022年3月13日编程语言C语言大约 9 分钟约 2779 字

C 语言基础

数据类型

C 语言中的关键字

auto、const、double、float、int、short、struct、unsigned

break、continue、else、for、long、signed、switch、void

case、default、enum、goto、register、sizeof、typeof、volatile

char、do、extern、if、return、static、union、while

变量代表内存中具有特定属性的一个存储单元,它用来存放数据,即变量的值。这些值在程序的执行过程中是可以改变的。

变量名实际上以一个名字代表一个对应的存储单元地址。编译、链接程序时,由编译系统为每个变量名分配对应的内存地址。从变量中取值实际上是通过变量名找到内存中存储单元的地址,并从该存储单元中读取数据。

变量的命名规定如下:C 语言规定标识符只能由字母、数字和下画线三种字符组成,并且第一个字符必须为字母或下画线。例如:

sum, _total, month, Student_name, lotus_1_2_3, BASIC, li_ling

是正确的,而

M.D.John, ¥123, 3D64, a>b

是错误的。

编译系统认为大写字母和小写字母是不同的字符,因此 C 语言要求对所有用到的变量做强制定义,即“先定义,后使用”。同时在选择变量名和其他标识符时,应尽量做到“见名知意”,即选择具有含义的英文单词(或其缩写)作为标识符。注意,变量名不能与关键字同名!

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

#define PI 3 // PI就是符号常量

int main() {
    int a = 3; // a 就是一个变量
    a = 5;
    // PI = 10; 错误的,符号常量不可以赋值
    return 0;
}

整型常量的不同进制表示

计算机中只能存储二进制数,即 0 和 1,而在对应的物理硬件上则是高、低电平。为了更方便地观察内存中的二进制数情况,除我们正常使用的十进制数外,计算机还提供了十六进制数和八进制数。

下面介绍不同进制数的对应关系。

首先,在计算机中,1 字节为 8 位,1 位即二进制的 1 位,它存储 0 或 1。int 型常量的大小为 4 字节,即 32 位。

设有二进制数 0100 1100 0011 00010101 0110 1111 1110,其最低位是 2 的零次方,最高位是 2 的 30 次方,最高位为符号位,具体情况需要学习计算机组成原理。

上面的二进制数对应的八进制数是 011414253376,它以 0 开头标示,数位的变化范围是 0~7。二进数转换为八进制数的方式是,对应的二进制数每 3 位转换为 1 位八进制数。首先将上面的二进制数按每 3 位隔开,得到 01 001 100 001 100 010 101 011011 111 110,然后每 3 位对应 0~7 范围内。

scanf 函数

C 语言未提供输入/输出关键字,其输入和输出是通过标准函数库来实现的。C 语言通过 scanf 函数读取键盘输入,键盘输入又被称为标准输入。当 scanf 函数读取标准输入时,如果还没有输入任何内容,那么 scanf 函数会被卡住(专业用语为阻塞)。下面来看一个例子:

int main() {
    int a;
    scanf("%d", &a); // 一定要在变量前加入取地址符,即&符号
    printf("a=%d", a);
    return 0;
}

运行之后,输入任意数字再按下回车键,就会打印 “a=你输入的数字”。scanf 函数可以允许有多个参数下面是例子:

int a, b;
scanf("%d%d", &a, &b); // 一定要在变量前加入取地址符,即&符号
printf("a=%d, b=%d\n", a, b);

这时,需要输入两个数字(用空格隔开),按下回车键后就会按printf的格式输出。

常用进制

int main() {
    int i_2 = 0b01111011; // 2进制,以 "0b" 开头
    int i_8 = 0173; // 8进制,以数字 "0" 开头
    int i_10 = 123; // 10 进制
    int i_16 = 0x7b; // 16 进制,以 "0x" 开头
    printf("%o, %o, %o, %o\n", i_2, i_8, i_10, i_16); // %o 以八进制方式输出整型数
    printf("%d ,%d ,%d ,%d\n", i_2, i_8, i_10, i_16); // %d 以十进制方式输出整型数
    printf("%x, %x, %x, %x\n", i_2, i_8, i_10, i_16); // %x 以十六进制方式输出整型数
    return 0;
}

浮点数

C 语言中通过 float f 来定义浮点变量,f 占用 4 个字节的空间。

基本使用:

float f = 1.234;
printf("浮点数f = %f", f); // %f 是以浮点数形式输出数据

输出为:

浮点数f = 1.234000

提示

直接使用 1.234 会有类似 Clang-Tidy: Narrowing conversion from 'double' to 'float' 的警告,也就是说把一个双精度浮点数赋值给一个float型变量会丢失精度,因此建议在数字后加一个字母f,即1.234f

其他形式:

float f2 = 1.234f;
float f3 = 3e2f;
float f4 = 32.56e-4f;
printf("f2 = %f\n", f2);
printf("f3 = %f\n", f3);
printf("f4 = %f\n", f4);
输出
f2 = 1.234000
f3 = 300.000000
f4 = 0.003256

这里3e2f32.56e-4f 都是以IEEE754标准,类似“科学计数法”,即:

注意

字母eE之前必须有数字,且之后的指数必须是整数。

正确示例:1e31.8e-3-123e-6-.1e-3

错误实例:e32.1e3.5.e3e

字符型数据

单引号括起来的一个字符是字符型常量,且只能包含一个字符。例如,'a''A''1'' ' 是正确的字符型常量,而'abc'"a"" "是错误的字符型常量。

\ 开头的特殊字符称为转义字符,转义字符用来表示回车、退格等功能键。下表中给出了部分转义字符及其作用。

转义字符意义
\n换行(LF),将当前位置移到下一行开头
\t水平制表符(跳到下一个 TAB 位置)
\0空字符(NULL)
\\代表反斜线字符\
\'代表一个单引号字符
\"代表一个双引号字符

字符型变量使用关键字 char 进行定义,一个字符型变量占用 1 字节大小的空间。一个字符常量存放到一个字符型变量中时,实际上并不是把该字符的字型放到内存中,而是把该字符的 ASCIl 码值放到存储单元中,每个字符的 ASCII 码值详见ASCII 码表open in new window。打印字符型变量时,如果以字符形式打印,那么计算机会到 ASCII 码表中查找字符型变最的 ASCII 码值,查到对应的字符后会是示对应的字符。这样,字符型数据和整型数据之间就可以通用。字符型数据既可以以字符形式输出,又可以以整数形式输出,还可以通过运算获取想要的各种字符。例如,小写字母a的十进制 ASCII 码为97,可以通过以下代码验证:

int main() {
    char c = 'a';
    printf("%c, %d\n", c, c);
    printf("%c\n", 97);
    return 0;
}
输出
a, 97
a

对于字符型变量,无论是赋 ASCII 码值还是赋字符,使用 %c 打印输出时得到的都是字符,使用 %d 打印输出时得到的都是 ASCII 码值。

将小写字母转换为大写字母时,由 ASCII 码表发现小写字母与大写字母的差值为 32,因此将变量 c 减去 32 就可以得到大写字母 A。以下是代码:

int main() {
    char c, d; // 声明两个变量
    c = 97;
    d = 'a';
    printf("c = %c, d = %c\n", c, d); // 打印都是字母a
    printf("c = %d, d = %d\n", c, d); // 打印都是97

    c = c - 32; // 小写字母a,转换成大写字母A
    d = d - 32; // 观察 ASCII 码表得知,大小写之间相差 32
    printf("c = %c, d = %c\n", c, d); // 打印都是字母A
    return 0;
}

字符串型数据

字符串型常量是由一对双引号插起来的字符序列。例如,"How do you do.""CHINA""a""$123.45" 都是合法的字符串型常量,我们可用语句 printf("How do you do.") 输出一个字符串。但要注意的是,'a' 是字符型常量,而 "a" 是字符串型常量,二者是不同的。

例如,如果先用语句 char c 定义字符型变量 c,后令 c="a"c="CHINA",那么这样的赋值都是非法的,原因是不可以将字符串型常量赋值给字符型变量。

提示

C 语言中没有定义字符串型变量的关键字,而是用字符数组来存储。

C 语言规定,在每个字符串型常量的结尾加一个字符串结束标志,以便系统据此判断字符串是否结束。C 语言规定以字符 '\0' 作为字符串结束标志

例如,字符串型常量"CHINA"在内存中的存储结果如下图所示,它占用的内存单元不是 5 个字符,而是 6 个字符,即大小为 6 字节,最后一个字符为'\0'。然而,在输出时不会输出'\0',因为它无法显示。

强制类型转换

int main() {
    int i = 5;
    float j = i / 2; // 输出的是2
    float k = (float) i / 2; // 输出的是2.5
    printf("j = %f, k = %f\n", j, k);
    return 0;
}

因为变量 i 和 2 都是 int 类型,i / 2的类型也是整型,因此将其赋值给j时就得到;而对 i 强制转化为float 类型时,等号右侧的进行的运算是浮点型的除法,赋值给变量 k 就是 了。

运算符

算术运算符包含 +-*/% ,当一个表达式中同时出现这 5 种运算符时,先进行乘(*)、除(/)、取余(%),取余也称取模,后进行加(+)、减(-),也就是乘、除、取余运算符的优先级高于加、减运算符。除了 % 运算符外,其余几种运算符既适用于浮点型数又适用于整型数。当操作符的两个操作数都是整型数时,它执行整除运算,在其他情况下执行浮点型数除法。% 为取模运算符、它接收两个整型操作数,将左操作数除以右操作数,但它的返回值是余数而不是商。

由算术运算符组成的式子称为算术表达式,表达式一定有一个值。以下代码中,变量 s 用于帮助读者理解算术运算符的优先级。

int s = 4 + 5 * 2 - 6 / 3 + 10 % 4;
printf("%d", s); // 14
2023-9-14 更新
重启 search-pro,css 样式调整