C 语言从回忆到重识 -- 1基础知识
资料来源:《C Primer Plus 6》
基础知识
发明者
- Dennis Ritch
- Ken Thompson
C 语言标准
- 最初:K&R C
- 第一个 ANSI/ISO C 标准:ANSI C (即 C89)
- 国际化标准组织与1990年采用了这套 C 标准(ISO C 即 C90),ISO C 和 ANSI C 是完全相同的标准;
- 信任程序员
- 不要妨碍程序员做需要做的事
- 保持语言精练简单
- 只提供一种方法执行一项操作
- 让程序运行更快,即使不能保证其可移植性
- 国际化标准组织与1990年采用了这套 C 标准(ISO C 即 C90),ISO C 和 ANSI C 是完全相同的标准;
- C99 标准
- ANSI/ISO 联合委员会最终于 1999 年发布
- 遵循最初 C90 标准
- 支持国际化编程
- 弥补缺陷
- 提高计算的实用性
- C11 标准
- 2011 年发布
C 语言是编译型语言;
使用步骤
- 定义程序目标
- 设计程序
- 编写代码
- 编译
- 运行程序
- 测试和调试程序
- 维护和修改程序
C 语言是可移植性语言;
helloC.c
#include <stdio.h>
int main(void) {
printf("你好");
return 0;
}
链接器
在 C 语言中,所有变量必须先声明才能使用;
关键字和保留标识符
- K&R
- auto
- break
- case
- char
- continue
- default
- do
- double
- else
- extern
- float
- for
- goto
- if
- int
- long
- register
- restrict
- return
- short
- sizeof
- static
- struct
- switch
- typedef
- union
- unsigned
- void
- while
- C90
- signed
- enum
- volatile
- C99
- inline
- C11
- _Alignas
- _Alignof
- _Atomic
- _Bool
- _Complex
- _Generic
- _Imaginary
- _Noreturn
- _Static_assert
- _Thread_local
数据和C
- 常量 constant
- 变量 variable
数据类型
- K&R
- int
- long
- short
- unsigned
- char 存储字符(字母或标点 即 ASCII 码)
- float %f %.2f
- double %f、%e(科学计数法)
- C90
- signed
- void
- C99
- _Bool true false
- _Complex 复数
- _Imaginary 虚数
以上除 void 外,均为基本数据类型;
数据类型组合
- short int
- long int
- long long int (C99)
- long long (C99)
- long double
- unsigned 无符号
- unsigned int (C90)
- unsigned long int (C90)
- unsigned long (C90)
- unsigned short (C90)
- unsigned long long int (C99)
- unsigned long long (C99)
转义字符
指针 pointer (前缀 & ),
scanf(”%d“, &value);
类型大小:
printf("size is %zd \n", sizeof(long));
sizeof 为内置运算符;
字符串
strlen 函数
#include <stdio.h>
#include <string.h>
void testChar(void) {
char name[40];
int size, letters;
printf("please input:");
scanf("%s", name);
size = sizeof name;
letters = strlen(name);
printf("name is %s , sizeof is %d , strlen is %d \n", name, size, letters);
}
// name is hello , sizeof is 40 , strlen is 5
注意:name 没有使用前缀 & ;但如果输入的是 int 型的变量则需要加 & 前缀,因为 name 是 char 数组的名称,本身就是地址索引;
注意:scanf() 读取字符串时只能读取一个单词,若需要读取一个完整的句子,可以使用 fgets() 函数;
预处理器指令 #define
- 用于定义常量,值不可改变;
- 编译程序时,会统一替换:
compile-time substitution
- 格式 :
#define NAME value
#define PI 3.1415926
void testDefine(void) {
float area = 3 * 3 * PI;
printf("PI is %.2f", area);
}
字符串
- 字符串本质上是 char 数组
- 包裹在双引号 ”“ 之间
- 以空字符
'\0'
结尾(空字符 \0 是非打印字符,其 ASCII 码为 0)- 例如字符串 ”a“ ,其本质是由两个 char 组成 :‘a’、’\0’
#include <stdio.h>
#include <string.h>
#define HELLO "hello"
void testLength(void) {
printf("string is %s , sizeof is %lu , strlen is %lu \n", HELLO, sizeof(HELLO), strlen(HELLO));
}
// string is hello , sizeof is 6 , strlen is 5
即 sizeof 的长度包含 ‘\0’ ;
const 限定符
- C90 标准新增的关键字,用于限定一个变量为只读;
const int MONTHS = 12; // 在程序中不可更改
limits.h
和float.h
头文件中包含一些常用的 明示常量
I/O 函数
- printf()
- scanf()
长字符串
printf("这是一个"
"长句子\n");
运算符和表达式
运算符
- 赋值运算符 =
- 加法运算符 +
- 减法运算符 -
- 符号运算法
-
- 乘法运算符 *
- 除法运算符 /
- sizeof 运算符和 size_t 类型
- C 语言规定,sizeof 返回 size_t 类型的值(这是一个无符号整数类型)
- 求模运算符 %
- 递增运算符 ++
- 递减运算符 –
- 相等运算符 ==
typedef int 别名;
别名 x = 2;
表达式和语句
表达式 由运算符和运算对象组成;
强制类型转换
long x = 2L;
int mice = (int)1.6 + (int)x;
理论情况下,应该避免自动类型转换,尤其是类型降级(导致精度失真);
循环
- for
- while
- do while
关系运算符
- <
- <=
>
>=
- ==
- !=
while
void testWhile(int x) {
int i = 0, sum = 0;
while (i < x) {
sum = sum + i;
i++;
}
printf("1 + ... + n = %d (n = %d) \n", sum, x);
}
在 C 中,所有非零视为
真
,只有 0 被视为假
;
C99 新增类型 _Bool 类型表示真假;(C99 还提供了stdool.h ,该头文件让 bool 定义为 _Bool 的别称);
优先级
for
void testFor(int x) {
int i, sum = 0;
for (i = 0; i <= x; i++) {
sum = sum + i;
}
printf("1 + ... + n = %d (n = %d) \n", sum, x);
}
其它赋值运算符
- +=
- -=
- *=
- /=
- %=
出口条件循环 do while
字符数组和字符串
分支和跳转
关键字
- if else
- switch case default
- continue
- break
- goto
if else
int testIfelse(int x) {
if (x >= 60) {
return x;
} else if (x >= 30) {
return x / 2;
} else {
return 0;
}
}
putchar
#include <stdio.h>
#define SPACE ' '
void putcharTest(void) {
char ch = getchar();
while (ch != '\n') {
if (ch == SPACE) {
putchar(ch);
} else {
putchar(ch + 1);
}
ch = getchar();
}
putchar(ch);
}
ctype.h 字符函数
逻辑运算符
- &&
- ||
- !
iso646.h
可以用 and
代替 &&
, or
代替 ||
, not
代替 !
;
#include <iso646.h>
int testIso646(int x) {
if (x % 2 == 0 and x % 3 == 0) {
return x;
}
if (x / 5 == 0 or x / 7 == 0) {
return x;
}
if (not x / 100 == 0) {
return x;
}
return 0;
}
优先级
a > b && b > c || b > d 相当于 ((a > b)&&(b > c)) || (b > d)
?= (三目运算符)
int test1(int x) {
return x < 0 ? -x : x;
}
continue break
- continue 继续循环 (只能用于循环中)
- break 退出执行 (可用于循环和 switch 语句中)
switch case default
void testSwitch(int x) {
switch (x) {
case 0:
printf("%d", x);
case 1:
printf("%d", x);
break;
case 2:
case 3:
case 4:
printf("x>1 --> %d", x);
default:
printf("not print");
}
}
goto
goto 语句在 C 中仍然可用,但是 C 不用 goto 语句也能运行良好;K&R 提到 goto 语句 易被滥用
,并建议谨慎使用,或者根本不用
;
void testGoto(int x) {
int flag, bill;
if (x > 12)
goto a;
goto b;
a:
x = x * 1.05;
flag = 2;
b:
bill = x * flag;
}
字符输入输出和输入验证
略