跳转至

C程序设计语言

C语言历史

C语言发展史

时间 名称 组织
1960 原型A语言 ALGOL语言
1963 CPL语言 剑桥大学
1967 BCPL语言 剑桥大学
1970 B语言 贝尔实验室
1973 C语言 贝尔实验室

C语言标准历程

标准 时间 说明
K&R C 1978 K&R C
ANSI C 1989 美国标准
ISO C90 1990 国际标准
ISO C99 1999 国际标准
ISO C11 2011 国际标准
ISO C17 2017 国际标准
  • 1978年,丹尼斯·里奇和布莱恩·柯林汉(Brian Wilson Kernighan)合作出版了《C程序设计语言》的第一版。 书中介绍的C语言标准也被C语言程序员称作"K&R C"(柯里C),第二版的书中也包含了一些ANSI C的标准。 即使在后来ANSI C标准被提出的许多年后,K&R C仍然是许多编译器的最低标准要求,许多老旧的编译仍然运行K&R C的标准。
  • C89 和 C90 除卷首和截面编号外完全相同

C语言早期发展

  • 1969-1973年在美国电话电报公司(AT&T)贝尔实验室开始了C语言的最初研发。
  • 根据C语言的发明者丹尼斯·里奇 (Dennis Ritchie) 说,C 语言最重要的研发时期是在1972年。
  • 说明:丹尼斯·里奇(Dennis Ritchie),C语言之父,UNIX之父。
  • 1978年与布莱恩·科尔尼干(Brian Kernighan)一起出版了名著《C程序设计语言(The C Programming Language)》,现在此书已翻译成多种语言,成为C语言方面最权威的教材之一。
  • 2011年10月12日(北京时间为10月13日),丹尼斯·里奇去世,享年70岁。
  • C语言之所以命名为C,是因为C语言源自Ken Thompson发明的 B语言,而B语言则源自BCPL语言。
  • C语言的诞生是和UNIX操作系统的开发密不可分的,原先的UNIX操作系统都是用汇编语言写的,1973年UNIX操作系统的核心用C语言改写,从此以后,C语言成为编写操作系统的主要语言。

K&R C

  • 1978年,丹尼斯·里奇(Dennis Ritchie)和布莱恩·科尔尼干(Brian Kernighan)出版了一本书,名叫《The C Programming Language》(中文译名为《C程序设计语言》)。
  • 这本书被C语言开发者们称为"K&R",很多年来被当作C语言的非正式的标准说明。
  • 人们称这个版本的C语言为"K&R C"。1988年丹尼斯·里奇(Dennis Ritchie)和布莱恩·科尔尼干(Brian Kernighan)修改此书,出版了《The C Programming Language》第二版,第二版涵盖了ANSI C语言标准。
  • 第二版从此成为大学计算机教育有关C语言的经典教材,多年后也没再出现过更好的版本。

ANSI C 和 ISO C

  • 1970到80年代,C语言被广泛应用,从大型主机到小型微机,也衍生了C语言的很多不同版本。
  • 为统一C语言版本,1983年美国国家标准局(American National Standards Institute,简称ANSI)成立了一个委员会,
  • 来制定C语言标准。1989年C语言标准被批准,被称为ANSI X3.159-1989 "Programming Language C"。
  • 这个版本的C语言标准通常被称为ANSI C。
  • 又由于这个版本是 89 年发布的,因此也被称为 C89。
  • 后来 ANSI 把这个标准提交到 ISO(国际化标准组织),1990年被 ISO 采纳为国际标准,称为 ISO C。
  • 又因为这个版本是1990年发布的,因此也被称为C90。ANSI C(C89) 与 ISO C(C90)内容基本相同,主要是格式组织不一样。
  • 因为 ANSI 与 ISO 的C标准内容基本相同,所以对于C标准,可以称为ANSI C,也可以说是ISO C,或者 ANSI / ISO C。
  • 注意:以后大家看到 ANSI C、ISO C、C89、C90,要知道这些标准的内容都是一样的。
  • 目前,几乎所有的开发工具都支持 ANSI / ISO C 标准。是C语言用得最广泛的一个标准版本。

C99

  • 在ANSI C标准确立之后,C语言的规范在很长一段时间内都没有大的变动。
  • 1995年C程序设计语言工作组对 C语言进行了一些修改,成为后来的1999年发布的 ISO/IEC 9899:1999标准,通常被成为C99。
  • 但是各个公司对C99的支持所表现出来的兴趣不同。
  • 当GCC和其它一些商业编译器支持C99的大部分特性的時候,微软和Borland却似乎对此不感兴趣。说明:GCC(GNU Compiler Collection,GNU编译器集合)是一套由GNU工程开发的支持多种编程语言的编译器。

C语言特点

  • 基础性语言。
  • 语言简洁、紧凑、方便、灵活。
  • 运算符、数据结构丰富。
  • 结构化、模块化编程。
  • 移植性好、执行效率高。(与写者有关,凭心而论移植性没有那么好)
  • 允许直接对硬件操作。

C课程讲解思路

专项练习名称 重点和建议
无输入专项 练习结构、基本语法、熟悉OJ
输入输出专项(一) 理清该类问题的基本形式、做简单输入
输入输出专项(二) 输入形式多样化、计算内容复杂化
类型转换专项 练习类型转换函数、求字节数等操作,多种类型 int、float、char、double、long long 等
格式化输入输出专项 练习多种形式的格式化输入输出函数
选择结构专项(一) 练习 if switch 结构。内容基础,单层逻辑,重点在运算关系上
选择结构专项(二) 练习多层复杂嵌套结构
循环结构专项(一) 练习基本的 for 循环形式
循环结构专项(二) 练习循环判断、统计、筛选等单层循环的基本题型
循环结构专项(三) 练习循环判断、统计、筛选等单层循环的基本题型
循环结构专项(四) 练习循环的嵌套表达
GCD 数位拆分 幂 自幂数 GCD LCM 质数 质因数分解
一维数组专项(一) 数组的基本形式和基本练习
一维数组专项(二) 练习数组的操作
指针 指针与数组
二维数组专项 二维数组基本操作练习
函数专题 函数的定义、传参、调用、函数栈
排序专题 sort、冒泡、选择、计数、插入
结构体专题 结构体、结构体排序
  • 数据结构与算法类
专项练习名称 重点和建议
枚举算法专题(基础算法) 基础枚举算法练习、基本函数的使用
模拟算法专题(基础算法) 基础模拟算法练习、双指针练习
高精度算法 高进度运算、快速幂
递推与贪心 递推、贪心
基础递归专题 基本的递归思想、递归与函数栈
栈和队列 栈、队列
搜索 深搜、广搜、递归树、自上而下
树、二叉树、波兰式、哈夫曼编码
有向、无向、有权、无权、最小生成树
查找算法专题 二分查找、顺序查找
DP 递归树优化、自下而上
字符串 KMP
  • 应用类
专项练习名称 重点和建议
freopen 练习使用freopen
字符串处理专项 string的基本操作,库操作
STL STL相关函数使用

一些思想

  • 有些人认为c语言是自由的、灵活的语言。
  • 它信任程序员所编程的程序。
  • 它希望程序员方便的实现各种功能。
  • 在程序员清楚自己做什么的情况下,它甚至允许数组越界。

主函数

#include <stdio.h>

/*
   主函数不同编译器写法
   void main(void);
   void main(int argc, char** argv);
   void main(int argc, char* argv[]);
   int main(int argc, char** argv);
   int main(int argc, char* argv[]);
   int main(void) 
*/

int main(void)
{
    printf("Hello, World\n");
    return 0;
}

gcc

c源程序到可执行程序的过程

c源程序 -> 预处理 -> 编译 -> 汇编 -> 链接 -> 可执行文件

  1. 预处理。程序中以'#'号开头的部分在这个时候处理。预处理文件以.i结尾。

    gcc -E hello.c > hello.i
    

  2. 编译。编译出汇编文件,汇编文件以.s结尾。

    gcc -S hello.i
    

  3. 汇编。对汇编文件进行汇编生成以.o结尾的目标文件。

    gcc -c hello.s
    

  4. 链接。将目标文件链接后生成可执行文件。

    gcc hello.o -o hello
    

gcc编译器的说明

  • 编译时显示所有的错误或警告
    gcc hello.c -Wall
    

一些描述

  • 很多编译器特殊化了main函数,作为进程的入口或出口。main就是一个正在运行的线程。
  • 大部分情况下void 可以赋值给任何类型的指针。任何类型的指针也可以赋值给void
  • //(内核中对进程和线程无意识区别,只理解为进程。计算机理解的经常大概和我们理解的进程有所区别。)
  • c语言的变量讲究先定义后使用。在以前严格的编译器上,甚至都不支持及时定义及时使用。
  • 习惯上c语言主函数完成后return 0表示成功,如果失败则用一个非0值表示。但主函数并不是默认返回0。return 0的结果是给其父进程看的。
  • printf函数的返回值为输出字符的数量。
  • shell中 echo $? 输出上一个语句的结果。
  • #if 0 ----- endif 在预处理阶段忽略
  • 算法。(表述形式:流程图,NS图,有限状态机FSM)
  • 防止写越界,防止内存泄露,谁打开谁关闭,谁申请谁释放。

注意点

  • \n 起到刷新键盘缓冲区的作用

    printf("hello,world\n");
    

  • 必须包含相应的头文件

    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    
    int main(void)
    {
        FILE *fp = NULL;
        fp = fopen("tmp", "r");
        if (fp == NULL)
        {
            // strerror 头文件 string.h
            // errno    头文件 errno.h
            fprintf(stderr, "fopne():%s\n", strerror(errno));
        }
        return 0;
    }
    

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    // malloc 头文件 stdlib.h
    int *p = malloc(sizeof(int));
    if (p == NULL)
        return -1;
    return 0;
}
  • return 0 返回的内容给当前进程的父进程。