c 语言知识点总结

# [email protected]
# 2018-01-02

是什么?
为什么?
怎么办?

* 前序
C是一种通用的程式語言,广泛用于系统软件与应用软件的开发。于1969年至1973年間,為了移植與開發UNIX作業系統,由丹尼斯·里奇與肯·汤普逊,以B语言为基础,在贝尔实验室設計、开发出來。

C语言具有高效、灵活、功能丰富、表达力强和較高的可移植性等特点,在程序员中备受青睐,成为最近25年使用最为广泛的编程语言[2]。目前,C语言編譯器普遍存在於各種不同的操作系统中,例如Microsoft Windows、macOS、Linux、Unix等。C語言的設計影響了众多後來的程式語言,例如C++、Objective-C、Java、C#等。

二十世纪八十年代,為了避免各開發廠商用的C語言語法產生差異,由美國國家標準局為C語言訂定了一套完整的國際標準語法,稱為ANSI C,作為C語言的標準。二十世纪八十年代至今的有关程式開發工具,一般都支持符合ANSI C的語法。

* c语言的发展历程
- 早期發展
C語言最早由丹尼斯·里奇(Dennis Ritchie)為了在PDP-11電腦上運行的Unix系統所設計出來的程式語言,第一次發展在1969年到1973年之間。

C源于BCPL语言,后者由馬丁·理察德(Martin Richards)于1967年左右设计实现。BCPL是一门"无类型"的编程语言:它仅能操作一种数据类型,即机器字(machine word)。1970年,肯·汤普逊为运行在PDP-7上的首个Unix系统设计了一个精简版的BCPL,这个语言被称为B语言,它也是无类型的。

Unix最早運行在PDP-7上,是以組合語言寫成。在PDP-11出现後,丹尼斯·里奇與肯·汤普逊着手將Unix移植到PDP-11上,无类型的语言在PDP-11上愈发显得合适。PDP-11提供了多种不同规格大小的基本对象:一字节长的字符,两字节长的整型数以及四字节长的浮点数。B语言无法处理这些不同规格大小的对象,也没有提供单独的操作符去操作它们。

C语言最初尝试通过向B语言中增加数据类型的想法来处理那些不同类型的数据。和大多数语言一样,在C中,每个对象都有一个类型以及一个值;类型决定了可用于值的操作的含义,以及对象占用的存储空间大小。

1973年,Unix作業系統的核心正式用C語言改寫,這是C語言第一次應用在作業系統的核心編寫上。

1975年C语言开始移植到其他机器上使用。史蒂芬·強生实现了一套「可移植编译器」,这套编译器修改起来相对容易,并且可以为不同的机器生成代码。从那时起,C在大多数计算机上被使用,从最小的微型计算机到与CRAY-2超级计算机。C语言很规范,即使没有一份正式的标准,你也可以写出C程序,这些程序无须修改就可以运行在任何支持C语言和最小运行时环境的计算机上。

C最初在小型机器上实现,并且继承了一系列小语种编程语言的特点;与功能相比,C的设计者更倾向于简单和优雅。此外,从一开始,C语言就是为系统级编程而设计,程序的运行效率至关重要,因此,C语言与真实机器能力的良好匹配也就不足为奇。例如,C语言为典型硬件所直接支持的对象:字符,整数(也许有多种大小),以及浮点数(同样可能有多种大小)提供了相应的基本数据类型。


- K&R C
1978年,丹尼斯·里奇和布萊恩·柯林漢合作出版了《C程序设计语言》的第一版。書中介紹的C語言標準也被C語言程式設計師稱作“K&R C”,第二版的書中也包含了一些ANSI C的標準。K&R C主要介绍了以下特色:

    结构(struct)类型
    长整数(long int)类型
    无符号整数(unsigned int)类型
    把运算符=+和=-改为+=和-=。因为=+和=-會使得編譯器不知道使用者要處理i = -10還是i =- 10,使得處理上產生混淆。

即使在後來ANSI C標準被提出的許多年後,K&R C仍然是許多編譯器的最低標準要求,許多老舊的編譯仍然運行K&R C的標準。

- ANSI C 和 ISO C
1989年,C语言被美國國家標準協會(ANSI)标准化,編號為ANSI X3.159-1989。這個版本又稱為C89。标准化的一个目的是扩展K&R C,增加了一些新特性。

    void 函数
    函数返回 struct 或 union 类型
    void * 数据类型

1990年,国际标准化组织(ISO)成立 ISO/IEC JTC1/SC22/WG14 工作组,来规定国际标准的C语言,通过对ANSI标准的少量修改,最终製定了 ISO 9899:1990,又稱為C90。随后,ANSI亦接受國際標準C,並不再發展新的C標準。

K&R C语言到ANSI/ISO标准C语言的改进包括:

    增加了真正的标准库
    新的预处理命令与特性
    函数原型允许在函数申明中指定参数类型
    一些新的关键字,包括 const、volatile 与 signed
    宽字符、宽字符串与多字节字符
    对约定规则、声明和类型检查的许多小改动与澄清

WG14工作小组之後又於1994年,对1985年颁布的标准做了两处技术修订(缺陷修复)和一个补充(扩展)。下面是 1994 年做出的所有修改:

    3 个新的标准库头文件 iso646.h、wctype.h 和 wchar.h
    几个新的记号与预定义宏,用于对国际化提供更好的支持
    printf/sprintf 函数一系列新的格式代码
    大量的函数和一些类型与常量,用于多字节字符和宽字节字符

- C99
在ANSI的标准确立後,C语言的规范在一段时间内没有大的变动,然而C++在自己的标准化建立过程中继续发展壮大。《标准修正案一》在1994年为C语言建立了一个新标准,但是只修正了一些C89标准中的细节和增加更多更广的国际字符集支持。不过,这个标准引出了1999年ISO 9899:1999的发表。它通常被称为C99。C99被ANSI于2000年3月采用。

在C99中包括的特性有:

    增加了对编译器的限制,比如源程序每行要求至少支持到 4095 字节,变量名函数名的要求支持到 63 字节(extern 要求支持到 31)。
    增强了预处理功能。例如:
        巨集支持取可变参数 #define Macro(...) __VA_ARGS__
        使用巨集的时候,允许省略参数,被省略的参数会被扩展成空串。
        支持 // 开头的单行注释(这个特性实际上在C89的很多编译器上已经被支持了)
    增加了新关键字 restrict, inline, _Complex, _Imaginary, _Bool
        支持 long long, long double _Complex, float _Complex 等类型
    支持不定长的数组,即数组长度可以在运行时决定,比如利用变量作为数组长度。声明时使用 int a[var] 的形式。不过考虑到效率和实现,不定长数组不能用在全局,或 struct 与 union 里。
    变量声明不必放在语句块的开头,for 语句提倡写成 for(int i=0;i<100;++i) 的形式,即i 只在 for 语句块内部有效。
    允许采用(type_name){xx,xx,xx} 类似于 C++ 的构造函数的形式构造匿名的结构体。
    初始化结构的时候允许对特定的元素赋值,形式为:

        struct test{int a[3],b;} foo[] =  { [0].a = {1}, [1].a = 2 };

        struct test{int a, b, c, d;} foo =  { .a = 1, .c = 3, 4, .b = 5 };  // 3,4 是对 .c,.d 赋值的

    格式化字符串中,利用 \u 支持 unicode 的字符。
    支持 16 进制的浮点数的描述。
    printf scanf 的格式化串增加了对 long long int 类型的支持。
    浮点数的内部数据描述支持了新标准,可以使用 #pragma 编译器指令指定。
    除了已有的 __line__ __file__ 以外,增加了 __func__ 得到当前的函数名。
    允许编译器化简非常数的表达式。
    修改了 / % 处理负数时的定义,这样可以给出明确的结果,例如在C89中-22 / 7 = -3, -22 % 7 = -1,也可以-22 / 7= -4, -22 % 7 = 6。 而C99中明确为 -22 / 7 = -3, -22 % 7 = -1,只有一种结果。
    取消了函数返回类型默认为 int 的规定。
    允许在 struct 的最后定义的数组不指定其长度,写做 [](flexible array member)。
    const const int i 将被当作 const int i 处理。
    增加和修改了一些标准头文件,比如定义 bool 的 <stdbool.h> ,定义一些标准长度的 int 的 <inttypes.h> ,定义复数的 <complex.h> ,定义宽字符的 <wctype.h> ,类似于泛型的数学函数 <tgmath.h>, 浮点数相关的 <fenv.h>。 在<stdarg.h> 增加了 va_copy 用于复制 ... 的参数。<time.h> 里增加了 struct tmx ,对 struct tm 做了扩展。
    输入输出对宽字符以及长整数等做了相应的支持。

但是各个公司对C99的支持所表现出来的兴趣不同。当GCC和其它一些商业编译器支持C99的大部分特性的时候[4],微软和Borland却似乎对此不感兴趣。

- C11
2011年12月8日,ISO正式发布了新的C语言的新标准C11,之前被称为C1X,官方名称为ISO/IEC 9899:2011。

新的标准提高了对C++的兼容性,并增加了一些新的特性。这些新特性包括:

    对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符, aligned_alloc函数以及<stdalign.h>头文件。
    _Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。
    _Generic 关键字。
    多线程(Multithreading)支持,包括:
        _Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。
        _Atomic类型修饰符和<stdatomic.h>头文件。
    增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>.
    删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。
    增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。[5]
    增加了更多浮点处理宏。
    匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。
    静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
    新的 fopen() 模式,(“…x”)。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
    新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。




















* c语言的组成结构
- 設計
C語言設計目標是提供一種能以簡易的方式編譯、處理低階記憶體、產生少量的機械碼以及不需要任何執行環境支援便能執行的程式語言。C語言也很適合搭配汇编语言來使用。儘管C語言提供許多低階處理的功能,但仍保持良好跨平台的特性,以一個標準規格寫出的C語言程式可在許多電腦平台上進行編譯,甚至包含一些嵌入式处理器(微控制器或称MCU)以及超級電腦等作業平台。

- 特性

    C語言是一個有結構化程式設計、具有变量作用域(variable scope)以及遞迴功能的程序式語言。
    C語言傳遞參數均是以值傳遞(pass by value)[3],另外也可以傳遞指针(a pointer passed by value)。
    不同的變數類型可以用結構体(struct)組合在一起。
    只有32個保留字(reserved keywords),使变量、函數命名有更多彈性。
    部份的变量類型可以轉換,例如整型和字符型变量。
    透過指针(pointer),C語言可以容易的對記憶體進行低階控制。
    编译预处理(preprocessor)讓C語言的編譯更具有彈性。

- 語法

Hello World 程序

test.c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello World!\n");
    return 0;
}
# vim test.c
shizsun@shizsun-ThinkPad-T450:~/work/data/coding/work/book/c/samplecode$ gcc -o test test.c
shizsun@shizsun-ThinkPad-T450:~/work/data/coding/work/book/c/samplecode$ ./test
Hello World!

本测试程序test.c 是标准的helloworld程序,包含标准输入/输出头文件,程序入口main() 函数,标准的输出函数printf.

基本数据类型:
1.无符号:char/short/int/long/float/double
2.有符号:unsigned char/ unsigned short/ unsigned int/ unsigned long/ unsigned float/unsigned double
结构数据类型:
union/enum/struct/
数组类型

关键字(32个):
  char short int unsigned long float double struct
  union void enum signed const volatile typedef auto
  register static extern break case continue default do
  else for goto if return switch while sizeof

- C99新增关键字
_Bool     _Complex     _Imaginary     inline     restrict
- C11新增关键字
_Alignas     _Alignof     _Atomic     _Generic     _Noreturn
_Static_assert     _Thread_local

- 表达式
1.顺序
2循环 for do{}while()  while() goto
3条件  if else switch

- 运算符
算术 + - * /
关系 > < == <= >=
逻辑 & | !
赋值  = += -= *= /= ..
条件运算符:?=

指针
1.存放地址的变量

shizsun@shizsun-ThinkPad-T450:~/work/data/coding/work/book/c/samplecode$ cat point.c
#include <stdio.h>
#include <stdlib.h>


unsigned int *p3=NULL;

int main(int argc, char *argv[])
{
    unsigned int *p1=NULL;

    unsigned int *p2 = malloc(1024);
    if (NULL == p2){
        printf("malloc failed.\n");
        return -1;
    }

    printf("pointer1 address:%p[&p1=%p]\n",p1,&p1);
    printf("pointer2 address:%p[&p2=%p]\n",p2,&p2);
    printf("pointer3 address:%p[&p3=%p]\n",p3,&p3);
    return 0;
}
# ./point
pointer1 address:(nil)[&p1=0x7ffc05fc4aa0]
pointer2 address:0xb04010[&p2=0x7ffc05fc4aa8]
pointer3 address:(nil)[&p3=0x601058]

解析:p1 地址为0x7ffc05fc4aa0为栈空间指针,指针存放的地址数据为null;
  p2  地址为0x7ffc05fc4aa8为栈空间指针,指针存放的地址0xb04010,分布在堆空间里
  p3 地址为0x601058为数据段指针,指针存放的地址数据为null;

函数









未完待续...








猜你喜欢

转载自blog.csdn.net/u013926029/article/details/78954285