2022-10-13 01:19:47 +08:00

16 KiB
Raw Blame History

C 备忘清单

提供基本语法和方法的 C 快速参考备忘单。

入门

hello.c

#include <stdio.h>

int main() {
  printf("Hello World!");
  return 0;
}

使用 gcc 编译 hello.c 文件

$ gcc -o hello hello.c

运行编译后的二进制文件(hello)

$ ./hello
# 输出 => Hello World

变量

int myNum = 15;

int myNum2; // 不赋值,然后再赋值
myNum2 = 15;

int myNum3 = 15;  // myNum3 值为 15
myNum3 = 10;      // 现在 myNum3 值为 10

float myFloatNum = 5.99; // 浮点数
char myLetter = 'D';     // 字符串

int x = 5;
int y = 6;
int sum = x + y;  // 添加变量相加
// 声明多个变量
int x = 5, y = 6, z = 50;

常量 Constants

const int minutesPerHour = 60;
const float PI = 3.14;

最佳实践

const int BIRTHYEAR = 1980;

注释

// 这是一个注释
printf("Hello World!"); // 这是一个注释
/* 多行注释,上面的代码将打印出 Hello World!
到屏幕上,真是太棒了 */

打印文本

printf("I am learning C.");
int testInteger = 5;
printf("Number = %d", testInteger);

float f = 5.99; // 浮点数
printf("Value = %f", f);

short a = 0b1010110;  // 2 进制数字
int b = 02713;        // 8 进制数字
long c = 0X1DAB83;    // 16 进制数字

// 以 8 进制形似输出
printf("a=%ho, b=%o, c=%lo\n", a, b, c);
// 输出 => a=126, b=2713, c=7325603

// 以 10 进制形式输出
printf("a=%hd, b=%d, c=%ld\n", a, b, c);
// 输出 => a=86, b=1483, c=1944451

// 以 16 进制形式输出(字母小写)
printf("a=%hx, b=%x, c=%lx\n", a, b, c);
// 输出 => a=56, b=5cb, c=1dab83

// 以 16 进制形式输出(字母大写)
printf("a=%hX, b=%X, c=%lX\n", a, b, c);
// 输出 => a=56, b=5CB, c=1DAB83

控制空格数

int a1=20, a2=345, a3=700;
int b1=56720, b2=9999, b3=20098;
int c1=233, c2=205, c3=1;
int d1=34, d2=0, d3=23;

printf("%-9d %-9d %-9d\n", a1, a2, a3);
printf("%-9d %-9d %-9d\n", b1, b2, b3);
printf("%-9d %-9d %-9d\n", c1, c2, c3);
printf("%-9d %-9d %-9d\n", d1, d2, d3);

输出结果

20        345       700  
56720     9999      20098
233       205       1    
34        0         23   

%-9d 中,d 表示以 10 进制输出,9 表示最少占 9 个字符的宽度,宽度不足以空格补齐,- 表示左对齐

字符串 Strings

char greetings[] = "Hello World!";
printf("%s", greetings);

访问字符串

char greetings[] = "Hello World!";
printf("%c", greetings[0]);

修改字符串

char greetings[] = "Hello World!";
greetings[0] = 'J';

printf("%s", greetings);
// 输出 "Jello World!"

另一种创建字符串的方法

char greetings[] = {'H','e','l','l','\0'};

printf("%s", greetings);
// 输出 "Hell!"

C 没有 String 类型,使用 char 类型并创建一个字符 array

条件判断

int time = 20;
if (time < 18) {
  printf("再会!");
} else {
  printf("晚上好!");
}
// 输出 -> "晚上好!"
int time = 22;
if (time < 10) {
  printf("早上好!");
} else if (time < 20) {
  printf("再会!");
} else {
  printf("晚上好!");
}
// 输出 -> "晚上好!"

三元运算符

int time = 20;
(time < 18) ? printf("再会!") : printf("晚上好!");

Switch

int day = 4;

switch (day) {
  case 3: printf("周三"); break;
  case 4: printf("周四"); break;
  default:
    printf("期待周末");
}
// 输出 -> "周四" (day 4)

While 循环

int i = 0;

while (i < 5) {
  printf("%d\n", i);
  i++;
}

注意:不要忘记增加条件中使用的变量,否则循环永远不会结束,成为“死循环”!

Do/While 循环

int i = 0;

do {
  printf("%d\n", i);
  i++;
} while (i < 5);

For 循环

int i;

for (i = 0; i < 5; i++) {
  printf("%d\n", i);
}

跳出循环 Break/Continue

int i;

for (i = 0; i < 10; i++) {
  if (i == 4) {
    break;
  }
  printf("%d\n", i);
}

i 等于 4 时跳出循环

int i;

for (i = 0; i < 10; i++) {
  if (i == 4) {
    continue;
  }
  printf("%d\n", i);
}

示例跳过 4 的值

While Break 示例

int i = 0;

while (i < 10) {
  if (i == 4) {
    break;
  }
  printf("%d\n", i);
  i++;
}

While continue 示例

int i = 0;

while (i < 10) {
  i++;
  if (i == 4) {
    continue;
  }
  printf("%d\n", i);
}

数组 Arrays

int myNumbers[] = {25, 50, 75, 100};
printf("%d", myNumbers[0]);
// 输出 25

更改数组元素

int myNumbers[] = {25, 50, 75, 100};
myNumbers[0] = 33;

printf("%d", myNumbers[0]);

循环遍历数组

int myNumbers[] = {25, 50, 75, 100};
int i;

for (i = 0; i < 4; i++) {
  printf("%d\n", myNumbers[i]);
}

设置数组大小

// 声明一个由四个整数组成的数组:
int myNumbers[4];
// 添加元素
myNumbers[0] = 25;
myNumbers[1] = 50;
myNumbers[2] = 75;
myNumbers[3] = 100;

枚举 Enum

enum week { Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };

定义枚举变量

enum week a, b, c;

enum week { Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a, b, c;

有了枚举变量,就可以把列表中的值赋给它

enum week { Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };
enum week a = Mon, b = Wed, c = Sat;
// 或者
enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a = Mon, b = Wed, c = Sat;

枚举示例应用

enum week {Mon = 1, Tues, Wed, Thurs} day;

scanf("%d", &day);

switch(day){
  case Mon:   puts("Monday"); break;
  case Tues:  puts("Tuesday"); break;
  case Wed:   puts("Wednesday"); break;
  case Thurs: puts("Thursday"); break;
  default:    puts("Error!");
}

用户输入

// 创建一个整数变量来存储我们从用户那里得到的数字
int myNum;

// 要求用户输入一个数字
printf("请输入一个数字: \n");

// 获取并保存用户输入的号码
scanf("%d", &myNum);

// 输出用户输入的数字
printf("您输入的数字: %d", myNum);

用户输入字符串

// 创建一个字符串
char firstName[30];
// 要求用户输入一些文本
printf("输入您的名字: \n");
// 获取并保存文本
scanf("%s", firstName);
// 输出文本
printf("Hello %s.", firstName);

内存地址

创建变量时,会为该变量分配一个内存地址

int myAge = 43;

printf("%p", &myAge);
// 输出0x7ffe5367e044

要访问它,请使用引用运算符 (&)

创建指针

int myAge = 43;      // 一个 int 变量
printf("%d", myAge); // 输出 myAge(43)的值

// 输出 myAge 的内存地址0x7ffe5367e044
printf("%p", &myAge);

指针变量

int myAge = 43;            // 一个 int 变量
int* ptr = &myAge;         // 名为 ptr 的指针变量,用于存储 myAge 的地址

printf("%d\n", myAge);     // 输出 myAge (43) 的值

printf("%p\n", \&myAge);   // 输出 myAge 的内存地址0x7ffe5367e044

printf("%p\n", ptr);       // 用指针0x7ffe5367e044输出myAge的内存地址

取消引用

int myAge = 43;     // 变量声明
int* ptr = &myAge;  // 指针声明

// 参考:用指针输出 myAge 的
// 内存地址0x7ffe5367e044
printf("%p\n", ptr);
// 取消引用:用指针输出 myAge 的值 (43)
printf("%d\n", *ptr);

运算符

算术运算符

int myNum = 100 + 50;
int sum1 = 100 + 50;    // 150 (100 + 50)
int sum2 = sum1 + 250;  // 400 (150 + 250)
int sum3 = sum2 + sum2; // 800 (400 + 400)

Operator Name Description Example
+ 将两个值相加 x + y
- 从另一个值中减去一个值 x - y
* 将两个值相乘 x * y
/ 将一个值除以另一个 x / y
% 取模 返回除法余数 x % y
++ 增量 将变量的值增加 1 ++
-- 乘量 将变量的值减 1 --x

赋值运算符

符号 示例 如同
= x = 5 x = 5
+= x += 3 x = x + 3
-= x -= 3 x = x - 3
*= x *= 3 x = x * 3
/= x /= 3 x = x / 3
%= x %= 3 x = x % 3
&= x &= 3 x = x & 3
|= x |= 3 x = x | 3
^= x ^= 3 x = x ^ 3
>>= x >>= 3 x = x >> 3
<<= x <<= 3 x = x << 3

比较运算符

int x = 5;
int y = 3;

printf("%d", x > y);
// 返回 1因为 5 大于 3

符号 名称 示例
== 等于 x == y
!= 不等于 x != y
> 大于 x > y
< 小于 x < y
>= 大于或等于 x >= y
<= 小于或等于 x <= y

比较运算符用于比较两个值

逻辑运算符

符号 名称 说明 示例
&& 逻辑 如果两个语句都为真,则返回真 x < 5 && x < 10
|| 逻辑 如果其中一个语句为真,则返回真 x < 5 || x < 4
! 逻辑 反转结果,如果结果为真则返回假 !(x < 5 && x < 10)

运算符示例

unsigned int a = 60; /* 60 = 0011 1100 */  
unsigned int b = 13; /* 13 = 0000 1101 */
int c = 0;           

c = a & b;      /* 12 = 0000 1100 */ 
printf("Line 1 - c 的值是 %d\n", c );

c = a | b;      /* 61 = 0011 1101 */
printf("Line 2 - c 的值是 %d\n", c );
c = a ^ b;      /* 49 = 0011 0001 */
printf("Line 3 - c 的值是 %d\n", c );
c = ~a;         /*-61 = 1100 0011 */
printf("Line 4 - c 的值是 %d\n", c );
c = a << 2;     /* 240 = 1111 0000 */
printf("Line 5 - c 的值是 %d\n", c );
c = a >> 2;     /* 15 = 0000 1111 */
printf("Line 6 - c 的值是 %d\n", c );

位运算符

运算符 描述 实例
& 按位与操作,按二进制位进行"与"运算 (A & B) 将得到 12 即为 0000 1100
| 按位或运算符,按二进制位进行"或"运算 (A | B) 将得到 61 即为 0011 1101
^ 异或运算符,按二进制位进行"异或"运算 (A ^ B) 将得到 49 即为 0011 0001
~ 取反运算符,按二进制位进行"取反"运算 (~A) 将得到 -61 即为 1100 0011
<< 二进制左移运算符 A << 2 将得到 240 即为 1111 0000
>> 二进制右移运算符 A >> 2 将得到 15 即为 0000 1111

数据类型 Data Types

基本数据类型

数据类型 大小 Size 范围 Range 描述 Description
char 1 字节 128 ~ 127 单个字符/字母/数字/ASCII
signed char 1 字节 128 ~ 127 -
unsigned char 1 字节 0 ~ 255 -
int 24 字节 32,768 ~ 32,767 存储整数
signed int 2 字节 32,768 ~ 32,767
unsigned int 2 字节 0 ~ 65,535
short int 2 字节 32,768 ~ 32,767
signed short int 2 字节 32,768 ~ 32,767
unsigned short int 2 字节 0 ~ 65,535
long int 4 字节 -2,147,483,648 ~ 2,147,483,647
signed long int 4 字节 -2,147,483,648 ~ 2,147,483,647
unsigned long int 4 字节 0 ~ 4,294,967,295
float 4 字节
double 8 字节
long double 10 字节

数据类型

// 创建变量
int myNum = 5;             // 整数
float myFloatNum = 5.99;   // 浮点数
char myLetter = 'D';       // 字符串
// 高精度浮点数据或数字
double myDouble = 3.2325467;
// 打印输出变量
printf("%d\n", myNum);
printf("%f\n", myFloatNum);
printf("%c\n", myLetter);
printf("%lf\n", myDouble);

数据类型 说 明
char 字符型
short 短整型
int 整型
long 长整型
float 单精度浮点型
double 双精度浮点型
void 无类型

基本格式说明符

格式说明符 数据类型
%d%i int 整数
%f float 单精度的十进制类型
%lf double 高精度浮点数据或数字
%c char 字符
%s 用于 strings 字符串

基本格式说明符

short int long
8 进制 %ho %o %lo
10 进制 %hd %d %ld
16 进制 %hx / %hX %x / %X %lx / %lX

数据格式示例

int myNum = 5;
float myFloatNum = 5.99; // 浮点数
char myLetter = 'D';     // 字符串
// 打印输出变量
printf("%d\n", myNum);
printf("%f\n", myFloatNum);
printf("%c\n", myLetter);

预处理器

预处理器指令

指令 描述
#define 定义宏
#include 包含一个源代码文件
#undef 取消已定义的宏
#ifdef 如果宏已经定义,则返回真
#ifndef 如果宏没有定义,则返回真
#if 如果给定条件为真,则编译下面代码
#else #if 的替代方案
#elif 如果 #if 条件为假,当前条件为
#endif 结束一个 #if……#else 条件编译块
#error 当遇到标准错误时,输出错误消息
#pragma 使用标准化方法,向编译器发布特殊的命令到编译器中
// 所有的 MAX_ARRAY_LENGTH 替换为 20
#define MAX_ARRAY_LENGTH 20
// 系统库中获取 stdio.h
#include <stdio.h>
// 本地目录中获取 myheader.h
#include "myheader.h"
#undef  FILE_SIZE
#define FILE_SIZE 42 // 取消已定义并定义为 42

预定义宏

描述
__DATE__ 当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量
__TIME__ 当前时间,一个以 "HH:MM:SS" 格式表示的字符常量
__FILE__ 这会包含当前文件名,一个字符串常量
__LINE__ 这会包含当前行号,一个十进制常量
__STDC__ 当编译器以 ANSI 标准编译时,则定义为 1

ANSI C 定义了许多宏,您可以使用这些宏,但是不能直接修改这些预定义的宏

预定义宏示例

#include <stdio.h>

int main() {
  printf("File :%s\n", __FILE__);
  printf("Date :%s\n", __DATE__);
  printf("Time :%s\n", __TIME__);
  printf("Line :%d\n", __LINE__);
  printf("ANSI :%d\n", __STDC__);
}

宏延续运算符(\

一个宏通常写在一个单行上。

#define  message_for(a, b)  \
    printf(#a " 和 " #b ": 我们爱你!\n")

如果宏太长,一个单行容纳不下,则使用宏延续运算符 \

字符串常量化运算符(#

#include <stdio.h>

#define  message_for(a, b)  \
  printf(#a " 和 " #b ": 我们爱你!\n")

int main(void) {
  message_for(Carole, Debra);
  return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

Carole 和 Debra: 我们爱你!

需要把一个宏的参数转换为字符串常量时,使用字符串常量化运算符 #

标记粘贴运算符(##

#include <stdio.h>

#define tokenpaster(n) printf ("token" #n " = %d", token##n)

int main(void){
  int token34 = 40;
  tokenpaster(34);
  return 0;
}

defined() 运算符

#include <stdio.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
  printf("Here is the message: %s\n", MESSAGE);  
  return 0;
}

参数化的宏

int square(int x) {
   return x * x;
}

宏重写上面的代码,如下:

#define square(x) ((x) * (x))

宏名称和左圆括号之间不允许有空格

#include <stdio.h>
#define MAX(x,y) ((x) > (y) ? (x) : (y))

int main(void) {
   printf("Max between 20 and 10 is %d\n", MAX(10, 20));  
   return 0;
}

另见