C语言的入门还是很简单的:
把这段代码输入文本编辑器vim,保存成hello.c文件:文件里的符号全是英文字符,别把分号打成中文字符。
然后用gcc编译器它,命令为:gcc hello.c
获得一个可运行的a.out文件,在命令行里直接运行它:./a.out
可以看到打印的hello world字符串。
如果gcc编译出来的a.out文件没有自动加执行权限,可以自己加上,命令为:
chmod +x a.out
初学者在这段代码里出的错误,基本都是忘了打结尾的分号,或者使用了中文字符而导致的。
学会了这段代码之后,C语言就可以算入门了。
这段代码虽然很短,但涉及到了头文件、宏、函数、字符串/数字 常量、return 语句,涵盖了C语言50%的常用语法吧
剩下的语法,就是一些运算符、if else、while for、switch case等语句类型。
1.C语言入门阶段的最后一关,是指针。
指针,是一个表示变量的内存地址的无符号整数,位数跟CPU的字长相同。
64位机上,指针是8个字节。
老式的32位机上,指针是4个字节。
指针的字节数,跟long类型的整数一样。
数组的指针,指的是数组的“首地址”:数组的第0号元素的内存地址。
C语言从0开始编号,数组元素的内存地址与它的编号一一对应:
&a[i] == (unsigned long)a + i * sizeof(a[0]);
所以,指针是一个unsigned long型的(无符号)整数。
指针变量,是一个保存某种类型的数据的内存地址的变量。
指针的类型,是它指向的数据的类型。
指针的++和--运算,一次跳过(它指向的)1个元素的字节数:int型指针++和--的变化是sizeof(int)个字节。
大多数系统上,sizeof(int) == 4.
2.C语言的文件读写,是关系到操作系统的。
上图是C语言的文件函数,下图是Linux的文件函数。
C语言标准库的文件函数,最终也是使用OS的系统调用(其他语言的标准库也一样)。
操作系统为了把功能提供给应用层,都有一套API:其中的重点就是文件和网络编程的API。
API这个词来自windows,Linux上一般叫系统调用(syscall)。
windows有它自己的应用编程框架(C#,VS),windows上的C语言都是通过VC++支持的:VC++,VS里的C++
现在,C语言的应用编程,主要还是在Linux上。
Linux的系统调用,是C程序员在学会了基础内容之后,下一个阶段要熟悉的。
Linux继承的是Unix,它的API和Unix的区别不大:
要熟悉Linux系统,最好的参考资料还是那本老书:Unix环境高级编程
这本书的作者理查德-史蒂文斯1999年就过世了,但他的书依然是最好的Linux编程书。
当然,最主要的参考资料还是Linux的man手册:在命令行里输入man open,就可以打开open()函数的手册,里面有open()函数的详细用法。
把man open换成man socket,就可以打开socket函数的手册。
对同一个词的介绍,在man手册里可能有好几页:一个是对同名的Linux命令的介绍,另一个是对同名的Linux函数的介绍。
如果直接man open打开的不是函数介绍,可以用man 2 open,或者man 3 open等,通过数字去选页数。
3.Linux的常用函数:
1)open, close, read, write, fcntl
这些都是跟文件相关的函数,作用跟函数名一样。
fcntl:可以给文件加锁,给socket设置非阻塞,用法比较复杂,可以参考man手册。
2)lseek
移动文件指针到哪个位置,用法跟C库的fseek一样。
3)socket, bind, listen, accept, connect, send / recv, sendto / recvfrom
这些都是网络编程的API,
socket:创建socket描述符,即网络文件的句柄。
Linux上一切都是文件,socket也被看做一个文件。
bind:绑定socket到某个IP和端口号。
listen:让socket进入监听状态,用于服务器端监听某个IP和端口号。
accept:用于服务器端接受用户的连接。
connect:用于客户端连接到服务器。
send / recv:TCP协议的数据发送和接收。
sendto / recvfrom:UDP协议的数据发送和接收。
关闭socket,也是使用close()函数。
4)epoll_create, epoll_wait, epoll_ctl
Linux的epoll异步事件机制,
用于同时监控多个socket网络连接的读写状态,并进行高并发的异步处理,它是网络服务器的核心函数。
俄罗斯人写的Nginx服务器,底层就是这3个函数。
5)setsockopt / getsockopt
设置或读取网络socket的状态,细节参考Linux man手册。
getsockopt的其中一个应用就是,它在异步连接时用于读取连接的错误码:相当于connect()函数的返回值,只是这个过程在异步获取的。
6)fork / execve
fork:以当前进程为蓝本,创建一个子进程。
execve:给当前进程加载一个新的可执行程序,并替换它的用户内存空间。
在多进程编程里,这2个是基本的函数,但一般并不常用。
多进程的网络服务器Nginx,就是用fork()创建多个进程的。
7)pthread_create
Linux上的pthread线程库的函数,用于在当前进程里创建一个线程。
pthread系列函数,也是一组跟多线程编程的函数。
4.汇编语言
不会汇编语言的C程序员,不是好程序员
实际上,想学明白C语言的话,还是要学汇编语言。
不会汇编语言的话,像全局变量、局部变量、动态库、内存、操作系统这些跟C语言有关的东西,也是很难学明白的。
C语言,既是个大号的汇编语言,又是个OS的应用层胶水。
C语言,既离不了汇编语言,也离不了OS。
汇编语言就3个关键:内存、寄存器、栈。
这条汇编代码运行之前,内存什么状态、寄存器什么状态、栈是什么状态?
这条汇编代码运行之后,内存什么状态,寄存器什么状态,栈是什么状态?
记住这6个状态,也就学会了汇编语言了。
5.算法
算法关系到数学,算法导论是最好的参考资料。
当然,数学越好,越容易学算法。
但OpenCV开源之后,大多数情况下,用不到自己写算法
跟图像处理、视觉识别相关的算法,OpenCV几乎都有。
算法工程师做的,更多是把这些基础算法整合成一个特定场景的识别模型。
6.图形界面
C语言可以选各种图形界面库,例如GTK,SDL,QT,etc.
想做界面程序的话,选一种自己看着顺眼的图形库,然后熟悉一下它的C语言API就行了。
一般来说,图形库的API都是支持多种语言的,C语言也是其中之一。