C语言

设计

C语言设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器代码以及不需要任何运行环境支持便能运行的编程语言。C语言也很适合搭配汇编语言来使用。尽管C语言提供许多低级处理的功能，但仍保持良好跨平台的特性，以一个标准规格写出的C语言程序可在许多电脑平台上进行编译，甚至包含一些嵌入式处理器（微控制器或称MCU）以及超级电脑等作业平台。

早期发展

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语言为典型硬件所直接支持的对象：字符，整数（也许有多种大小），以及浮点数（同样可能有多种大小）提供了相应的基本数据类型。

C11

2011年12月8日，ISO正式发布了新的C语言的新标准C11，之前被称为C1X，官方名称为ISO/IEC 9899:2011。新的标准提高了对C++的兼容性，并增加了一些新的特性。这些新特性包括泛型宏、多线程、带边界检查的函数、匿名结构等。

C18

C18没有引入新的语言特性，只对C11进行了补充和修正。

Hello World 程序

下面是一个在标准输出设备（stdout）上打印出"Hello, world!" 字符串的简单程序。类似的程序，通常作为初学编程语言时的第一个程序： 
1 #include <stdio.h>2 3 int main(void)4 {5     printf("Hello, world!\n");6     return 0;7 }

进一步了解

C语言由函数和变量组成，C的函数就像是Fortran中的子程序和函数。
在C语言中，程序从main 开始执行。main 函数通过调用和控制其他函数进行工作。例如上面的printf。程序员可以自己写函数，或从库中调用函数。在上面的return 0; 使得 main 返回一个值给调用程序的壳层，表明程序是否成功运行。
一个C语言的函数由返回值、函数名、参数列表和函数体组成。函数体的语法和其它的复合的语句部分是一样的。

复合语句

C语言中的复合语句（或称语句块）的格式为：
{
    語句;
    語句;
    /* ... */}
复合语句可以使得几个语句从文法上变成一个语句。
有时必须使用复合语句，否则会产生错误。例如，在运用循环语句的时候，如果循环体（即循环中执行部分）包含多个语句（以分号隔开），则必须使用花括号将他们合并成一个复合语句。如果不这么做，系统仅把第一个分号前的内容看做循环体。
需要注意的是，部分C编译器并不支持在任意位置使用复合语句。

条件语句

C语言有两种条件语句形式，分别是if和switch。
If 的格式如下：
if(運算式) // 如果
    語句; 
// 有時還會有else：else      // 否則
    語句;
表达式的值非零表示条件为真；如果条件为假，程序将跳过if处的语句，直接运行if后面的语句。但是如果if后面有else，则当条件为假时，程序跳到else处运行。if和else后面的语句可以是另个if语句，这种套叠式的结构，允许更复杂的逻辑控制流程得以实现。在一般情况下，else一定与最接近的if成对，因此常用括弧{}越过此限制。比较下面两种情况：
if(邏輯表達)
    if (邏輯表達式)
        語句; 
    else
        語句;
1 if(邏輯表達式甲)2 {3     if(邏輯表達式乙)4         語句;5 }6 else 
7     語句;
要注意这里的缩进和换行只用于方便阅读。编译器并不会根据缩进层级猜测if 和 else 的对应关系。
switch通常用于对几种有明确值的条件进行控制。它要求的条件值通常是整数或字符。与switch搭配的条件转移是case。使用case后面的标值，控制程序将跳到满足条件的case处一直往下运行，直到语句结束或遇到break。通常可以使用default把其他例外的情况包含进去。如果switch语句中的条件不成立，控制程序将跳到default处运行；如果省略default子句，则直接运行下一语句。switch是可以嵌套的。
switch(值){
  case 甲:
  case 乙:
    語句段1; // 甲乙都會執行
    // 更多語句…
    break;  // 跳轉到switch 末尾處
  case 丙:
    語句段2;
    break; 
  default:  // 無論如何都會匹配
    語句段3;}
简单的条件判断也可用?:
運算式?值1:值2;如:
   a=b>c?b:c // 如果變數"b"的值大於變數"c" 把變數"b"的值賦予變數"a"

循环语句

C语言有三种形式的循环语句：
do 
    語句while(判断式); 

和:while(判断式) 
    語句;和:for(起始化; 判断式;運算式)
    語句;
在while和for中，语句将运行到表达式的值为零时结束。在do...while语句中，循环将至少被运行一次。这三种循环结构可以互相转化：
for(起始化; 判断式;運算式)
    語句;
如果语句中不使用continue语句的话，相当于
初始化;while (判断式) {
    語句;
    運算式;}
当循环条件一直为真时，将产生死循环。

跳转语句

跳转语句包括四种：goto，continue，break和return。
goto 標記;
goto语句是无条件转移语句，且标记必须在当前函数中定义，使用“标记:”的格式定义。程序将跳到标记处继续运行。由于goto（特别是向回goto 和长距离的goto）容易产生阅读上的困难，所以对新手应该尽量少用。GCC 编译器拓展支持对指针goto和宏内goto，一定程度上增强了goto 的可读性。
continue语句用在循环语句中，作用是结束当前一轮的循环，马上开始下一轮循环。
break语句用在循环语句或switch中，作用是结束当前循环，跳到循环体外继续运行。但是使用break只能跳出一层循环。在要跳出多重循环时，可以使用goto使得程序更为简洁。
当一个函数运行结束后要返回一个值时，使用return。return可以跟一个表达式或变量。如果return后面没有值，将运行不返回值。

结构数据类型

结构数据类型允许构造由多个基础数据类型组合而成的复杂结构，结构数据类型为面向对象的蓝本。以下的结构数据类型通过指针实现了二叉树结构：
1 typedef struct Bintree {2     int data;3     struct bintree *lchild; // left child of the node4     struct bintree *rchild; // right child of the node5 } bintree; // 自定义bintree 类型
为结构数据类型定义变量时通常会用到动态内存分配：
1 #define mktree() (bintree *)malloc(sizeof(bintree)) // 分配该结构所需的内存单元数量2 bintree *tree;3 tree = mktree(); // 分配到tree 指针4 tree->data = 1;5 tree->lchild = mktree();6 ...
由于C语言不具备自动垃圾收集（Garbage Collection）功能，使用完毕后调用free(treePtr)来释放之前通过malloc(size)分配的内存。详见以下指针章节。

指针

如果一个变量声明时在前面使用* 号，表明这是个指针型变量。换句话说，该变量存储一个地址，而 *（此处特指单目运算符*，下同。C语言中另有双目运算符* 表示乘） 则是取内容操作符，意思是取这个内存地址里存储的内容。把这两点结合在一起，可将int *a;看作是“*a 解得的内容类型为int”，对更复杂的声明也如此。指针是C 语言区别于其他同时代高级语言的主要特征之一。
指针不仅可以是变量的地址，还可以是数组、数组元素、函数的地址。通过指针作为形式参数可以在函数的调用过程得到一个以上的返回值（不同于return z这样的仅能得到一个返回值。
指针是一把双刃剑，许多操作可以通过指针自然的表达，但是不正确的或者过分的使用指针又会给程序带来大量潜在的错误。
例如：
int *pi;     // 指向整型数据的指针piint * api[3];// 由指向整型数据的指针构成的数组，长度为3char ** argv;// 指向一个字符指针的指针struct { int member; } stinst,
  * pst = & stinst;// pst是一个指向一个匿名结构体的指针
储存在指针中的地址所指向的数值在程序中可以由* 读取。例如，在第一个例子中， *pi 是一个整型数据。这叫做引用一个指针。
另一个运算符&，叫做取地址运算符，它将返回一个变量、数组或函数的存储地址。因此，下面的例子：
int i, *pi; /* int and pointer to int */pi = &i;
i 和 *pi 在程序中可以相互替换使用，直到 pi 被改变成指向另一个变量的地址。
当指针指向结构体时，可以使用运算符-> 代替 *和. 的作用，如 (*p).m 与 p->m 等效。

字符串

C语言的字符串其实就是char型数组，所以使用字符串并不需要引用库。然而C标准库确实包含了用于对字符串进行操作的函数，使得它们看起来就像字符串而不是数组。使用这些函数需要引用头文件string.h。

文件输入／输出

在C语言中，输入和输出是经由标准库中的一组函数来实现的。在ANSI/ISO C中，这些函数被定义在头文件stdio.h中。

函数

C语言的基本结构单位是函数。系统首先调用main函数（主函数），通过函数的嵌套调用，再调用其他函数。函数可以是系统自带的函数，也可以是用户定义的函数。C语言中，不允许函数嵌套定义。

安全问题

C语言的特色之一是：语言不负责内存边界检查。此特性容易导致缓冲区溢出问题。

工具软件

工具软件可以帮助程序设计者避免一些程序中潜藏或容易出现的问题，例如常会造成程序未预期动作或是运行期错误的代码。
许多语言都有自动源代码检查及审计工具，C语言也有类似工具，像是Lint。可以在程序刚写好时用Lint找出可能有问题的程序，通过Lint后再用C编译器进行编译，许多编译器也可以设置是否要针对一些可能有问题的代码提出警告。MISRA C是一套针对嵌入式系统的法则，可主要也是避免一些可能有问题的代码。
也有一些编译器、程序库或操作系统可以处理一些非标准C语言的功能，例如边界值检查、缓存溢出侦测、序列化及自动垃圾回收功能。
使用像Valgrind或IBM Rational Purify等软件工具，或者连结有特别malloc函数的程序库，有助于找出一些运行期存储器使用的问题。

经典错误

“void main()”的用法并不是任何标准制定的。 C语言标准语法是“int main()”，任何实现都必须支持int main(void) { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }。 在 C++ 标准中，main的标准类型应是int，否则类型是由实现定义的。任何实现都必须支持int main() { /* ... */ }和int main(int argc, char* argv[]) { /* ... */ }。