最全的Linux教程,Linux从入门到精通
======================
-
linux从入门到精通(第2版)
-
Linux系统移植
-
Linux驱动开发入门与实战
-
LINUX 系统移植 第2版
-
Linux开源网络全栈详解 从DPDK到OpenFlow
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。
需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
int v =V(2,3,4) 则宏展开后为:int v= 234;
2、文件包含——指一个源文件可以将另一个源文件的全部内容包含进来。如:
#include “文件名”或
#include <文件名>
编译预处理时,将包含文件的全部内容复制到源文件中。在编译时作为一个源程序来编译。
3、条件编译——在预编译处理时,确定编译时要编译的部分。如:
#if def 标识符
程序段 1
#else
程序段 2
#endif
#if 表达式
程序段 1
#else
程序段 2
#endif
10、指针
10.1 变量的访问方式
1、直接访问——如:int a = 10;
2、间接访问——定义一个指针变量 p,存放变量 a 的首地址,通过 p 访问变量 a。则称指针变量 p 指向变量 a。
如:int a=10;int p1; p=&a;b=p1;
或*p1=100;等价于 a=100;
10.2 指针变量
1、指针变量的类型——是指该变量指向的内存数据的数据类型。
2、必须用引用变量的地址给指针变量赋值。
3、可以给指针变量赋值空值 null,防止指针变量存储随机值导致系统错误。
4、数组名代表数据的首地址。数组指针或数组名+1,指向下一个数组元素的存储地址。
声明格式:数据类型 *p ;
赋值格式:p=a;或 p=&a[0];
引用格式:p=常量;等价于 p[0]=常量;等价于 a[0]=常量;等价于a=常量;
*(p+1)=常量;等价于 p[1]=常量;等价于 a[1]=常量;
等价于*(a+1)=常量;
5、数组名和指针变量虽然都可以代表数组的首地址,但是指针变量值可以改变,而数组名的值不可以改变。
6、函数的指针专门用来存放函数的入口地址,当把函数的地址赋值给它时,它就指向该函数的入口地址。
声明格式:数据类型(指针变量名)()如:int (P)();
赋值格式:p=max; 注 max 为定义的函数名;函数名代表该函数的入口地址。
引用格式:c=(*p)(a,b);等价——c=max(a,b);
7、只能将变量已分配的地址赋值给指针变量,不能直接将整数赋值给指针变量。
8、指针变量可以有 null 值,防止指针误作用。
11、结构体
11.1 结构体
1、作用——将不同类型的数据组合成一个有机的整体。
2、结构体的定义——结构体是一种数据结构,按照某种规则定义,将若干个不同数据类型(也可相同)的数据项的组合成的一个有机整体。
3、声明结构体类型的形式:struct 结构体类型名字 {成员列表};
成员列表形式:类型符 成员名
如:int num;
11.2 声明结构体类型变量的方法
1、先定义结构体类型:struct 结构体类型名字 {成员列表};再定义结构体变量:
struct 结构体类型名字 结构体变量名。
2、可在定义结构体类型时,定义结构体类型变量。struct 结构体类型名字 {成员列表}结构体类型变量 1,结构体类型变量 2,……;
11.3 结构体变量引用
1、不能将一个结构体变量作为一个整体进行输入输出,只能对结构体变量成员分别赋值。
2、结构体变量成员引用方式:结构体变量名.成员名
3、如果结构体变量成员是另一个结构体变量,则要用若干个成员运算符,一级一级找到最低一级的成员。
11.4 结构体变量初始化
1、在声明变量时整体赋值。
2、复制相同结构的变量赋值。
3、除以上两种情况下可以对结构体类型变量整体赋值,其余情况下只能对变量成员分别赋值。
11.5 结构体数组
1、结构体数组在内存中连续存放。
2、声明方式:与定义结构体变量方法相同。见 11.2,只是在变量名后+[n]。也可在定义结构体数组时直接初始化结构体数组,此时可采用+[]的形式。
3、初始化方式:同定义结构体变量方法。
11.6 结构体类型指针
结构体类型指针——是指指向结构体变量所占据的内存的起始位置的指针。
声明形式:struct 结构体类型名 *指针名。如:struct student *p;
赋值形式:指针名=&结构体变量 。如:p=&studengt1;
引用形式:(P).成员名 或 p->成员名。p 表示指针 p 指向的结构体变量。
注意:
1、定义的结构体类型,和声明结构体变量时不分配空间。
2、结构体可以嵌套定义。
3、结构体成员名可以与变量名相同。
11.7 链表
1、单项链表结构:链表有一个头指针和表尾 null 指针。每个结点包含实际数据和下一个结点的地址。
11.8 共用体
1、共用体指将几种不同类型的变量存储在同一段内存单元中。
2、共用体变量的存储单元大小等于最长成员变量所占内存的长度
3、共用体变量中起作用的是最后一次存放成员。
4、共用体类型声明方式:union 公用体类型名称 {成员变量列表};
5、共用体变量声明方式:
(1)union 公用体类型名称 {成员列表}共用体变量;
(2)先声明共用体类型,然后声明共用体变量,union 公用体类型名称 共用体变量。
11.9 枚举类型
1、枚举类型——指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内的一个。
2、声明枚举类型:enum 枚举类型名称 {枚举常量列表};
3、声明枚举变量:enum 枚举类型名称 枚举类型变量;
11.10 用 typedef 定义的类型
1、typedef 的作用——可以用 typedef 声明新的类型名来代替已有的类型名。
2、声明方式:typedef 类型名称 新的类型名称。
12、位运算
12.1 位段
1、位段——是一种特殊的数据结构,它允许定义一个由位组成段,并可为它赋以一个名字。位段一般作为结构体的成员。
2、声明方法:
- 位段结构类型声明方法:struct 结构体类型名称 {位段成员列表};
- 位段结构成员(即位段变量)声明方法:unsigned int 位段变量 : n;
如:
struct packed_struct{
unsigned int f1 :1;
unsigned int f2 :1;
unsigned int f3 :1;
unsigned int type :4;
unsigned int index :9;
};
3、位段结构类型变量声明方法:同结构体。
4、同一位段必须存储在同一个存储单元中,不能跨两个单元。
13、文件
13.1 文件
1、文件——指存储在外部介质上的数据集合(数据文件),操作系统以文件为单位对数据进行管理。
13.2 文件的分类
1、从用户的观点看:
- 特殊文件——指标准输入输出文件或标准设备文件。
- 普通文件——指磁盘文件。
2、从操作系统的角度看:每一个与主机相关联的输入输出设备都可看作一个文
件。
(1)根据文件的组织形式分为:顺序存取文件 和 随机存取文件。
(2)根据文件的存储形式分为:ASCII 文件 和 二进制文件。
13.3 C 语言对文件的处理方法
C 语言中对文件的存取是以字符(字节)为单位的,一个输入输出流就是一个字节流或二进制流。
文件的存储方式分为缓冲文件系统和非缓冲文件系统。区别是缓冲文件系统是系统自动开辟缓冲区,非缓冲文件系统是由程序为每个文件设定缓冲区。
ANSI C 标准只采用 缓冲文件系统 来处理文件。
13.4 文件结构体类型
缓冲文件系统中,每个被使用的文件都在内存中开辟一个 FILE 结构体类型的区,用来存放文件的有关信息(文件名字、文件状态、当前位置、缓冲区等有关信息)。
FILE 结构体类型原型:
typedef struct{
short level; /缓冲区“满”或“空”的程度/
unsigned flags; /文件状态标志/
char fd; /文件描述符/
unsigned char hold; /如无缓冲区不读取字符/
short bsize; /缓冲区的大小/
unsigned char *buffer; / 数据缓冲区的位置/
unsigned char curp; /指针,当前的指向*/
unsigned istemp; /临时文件,指示器/short token;/用于有效性检查/}FILE;
13.5 文件结构体数组和指针
FILE *fp——声明了一个指向 FILE 类型结构体的指针变量。
FILE f[5]——声明了一个文件结构体数组 f,它有 5 个元素,存放 5 个文件的信息。
FILE 变量——声明了一个文件结构体变量。
13.6 文件的操作
C 语言要求,在文件读写之前要“打开”文件,在使用结束后要“关闭”文件。
1、打开文件:
FILE *fp;
fp=fopen(“文件名”,“使用文件方式”);指针变量指向被打开的文件。
例如:fp = fopen(“a1”,“r”)。
2、关闭文件:
fclose(文件指针);返回值:关闭成功返回值为0;否则返回 EOF(-1) 。
使文件指针变量不指向该文件,也就是文件指针变量与文件“脱钩”,此后不能再通过该指针对原来与其相联系的文件进行读写操作。
3、将字符写到文件中:
fputc ( ch,fp ) ;返回值:如果输出成功,则返回值就是输出的字符;如果输出失败,则返回一个 EOF(-1)。
将字符(ch 的值)输出到文件指针 fp 所指向的文件中去。该文件必须是以写或读写方式打开的。
4、将字符从文件中读出:
ch=fgetc(fp);返回值:读取成功一个字符,赋给 ch。如果遇到文件结束符,
返回一个文件结束标志 EOF(-1)。
从指定的文件读入一个字符,该文件必须是以读或读写方式打开的。
注意:ANSI C 提供一个 feof()函数来判断文件是否真的结束。如果是文件结束,函数 feof(fp)的值为1(真);否则为0(假)。以上也适用于文本文件的读取。
5、数据块读写:
fread (buffer,size,count,fp);
fwrite(buffer,size,count,fp);
buffer:是一个指针。对 fread 来说,它是读入数据的存放地址。对 fwrite 来说,
是要输出数据的地址(均指起始地址)。
size: 要读写的字节数。
count: 要进行读写多少个 size 字节的数据项。
fp: 文件型指针。
6、格式化读写函数:
fprintf ( 文件指针,格式字符串,输出表列);
fscanf ( 文件指针,格式字符串,输入表列);
注意:
用 fprintf 和 fscanf 函数对磁盘文件读写,使用方便,容易理解,但由于在输入时要将 ASCII 码转换为二进制形式,在输出时又要将二进制形式转换成字符,花费 时间比较多。因此,在内存与磁盘频繁交换数据的情况下,最好不用 fprintf 和 fscanf
函数,而用 fread 和 fwrite 函数。
7、以“字”或者整数为单位读写函数:
putw(int i,FILE * fp);
int i = getw(FILE * fp);
8、以“字符串”为单位读写文件的函数:
fgets(str,n,fp); 从 fp 指向的文件读出 n-1 个字符,在最后加一个’\0’。返回值:
str 的首地址。如果遇到 EOF 则读入结束。
fputs(“china”,fp); 把字符串写入到 fp 指向的文件。第一个参数可以是字符串常量、字符数组名或字符型指针。字符串末尾的′\0′不输出。
13.7 文件的定位
1、将文件当前的位置指针重新返回到文件的开头位置:无返回值。
rewind (fp);执行后,将文件的位置指针重新定位到文件的开头。
2、随机读写:改变文件的位置指针,一般用于二进制文件。- 18 -
fseek(文件类型指针,位移量,起始点);无返回值。
起始点:文件开头
SEEK_SET 0
文件当前位置
SEEK_CUR 1
文件末尾
SEEK_END 2
位移量:以起始点为基点,向后(前,末尾时)移动的字节数。一般要求为 long型。
3、获取流式文件当前的位置指针:返回当前位置——用相对于文件开头的位移量来表示。,出错时返回 EOF。
i = ftell(fp);
13.8 出错检测
1、ferror(fp);返回 0,表示未出错;返回非 0,表示出错。
注意:在调用一个输入输出函数后立即检查 ferror 函数的值,否则信息会丢失。
在执行 fopen 函数时,ferror 函数的初始值自动置为0。
2、clearerr(fp);使文件错误标志和文件结束标志置为 0。
只要出现错误标志,就一直保留,直到对同一文件调用 clearerr 函数或 rewind 函数,或任何其他一个输入输出函数。调用后feeror(fp)的值变为 0,且文件结束标志置为 0。
14、C++对C的扩充
14.1 C++的特点
1、C++保留了 C 语言原有的所有优点,增加了面向对象的机制。
2、C++源文件以.cpp 为后缀。
3、除了可以用 /……/ 形式的注释行外,还允许使用以// 开头的单行注释。
4、除了可以用 printf 函数输出信息外,还可以用 cout 进行输出。cout 的作用是将
<<运算符右侧的内容送到输出设备中输出。使用 cout 需要用到头文件 iostream.h,在
程序的第一行用#include 命令将该头文件“包含”进来。
cout <<" This is a c++ program.\ n" ;
14.2 C++的输入输出
C++为了方便使用,除了可以利用 printf 和 scanf 函数进行输出和输入外,还增加
了标准输入输出流 cout 和 cin。
cout 是由 c 和 out 两个单词组成的,代表 C++的输出流,
cin 是由 c 和 in 两个单词组成的,代表 C++的输入流。它们是在头文件 iostream.h 中定
义的。在键盘和显示器上的输入输出称为标准输入输出,标准流是不需要打开和关闭
文件即可直接操作的流式文件。
14.3 C++的输出 cout
1、cout 必须和输出运算符<<一起使用。<< 在这里不作为位运算的左移运算符,- 20 -
而是起插入的作用,例如:cout<<“Hello!\n”;的作用是将字符串“Hello!\n” 插入到输出
流 cout 中,也就是输出在标准输出设备上。
2、也可以不用\n 控制换行,在头文件 iostream.h 中定义了控制符 endl 代表回车换
行操作,作用与\n 相同。endl 的含义是 end of line,表示结束一行。
3、可以在一个输出语句中使用多个运算符<< 将多个输出项插入到输出流 cout
中,<<运算符的结合方向为自左向右,因此各输出项按自左向右顺序插入到输出流中。
每输出一项要用一个<< 符号。
例如:
for (i=1; i<=3;i++)
cout<<“count=”<<i<<endl;
输出结果为:
count=1
count=2
count= 3
4、用 cout 和<< 可以输出任何类型的数据。例如:
float a=3.45;
int b=5;
char c=′A′;
cout<<“a=”<<a<<“,”<<“b=”<<b<<“,”<<“c=”<<c<<endl;
5、如果要指定输出所占的列数,可以用控制符 setw 设置(注意:若使用 setw,必须
包含头文件 iomanip.h),如 setw(5) 的作用是为其后面一个输出项预留 5 列,如输出
项的长度不足 5 列则数据向右对齐,若超过 5 列则按实际长度输出。例如:
cout<<“a=”<<setw(6)<<a<<endl
<<“b=”<<setw(6)<<b<<endl
<<“c=”<<setw(6)<<c<<endl;
输出结果为:
a=3.45
b= 5
c= A
6、在 C++中将数据送到输出流称为“插入”(inserting) ,或“放到”(putting) 。<< 常称为“插入运算符”。
14.4 C++的输入 cin
1、输入流是指从输入设备向内存流动的数据流。标准输入流 cin 是从键盘向内存
流动的数据流。用>> 运算符从输入设备键盘取得数据送到输入流 cin 中,然后送到内
存。在 C++中,这种输入操作称为“提取”(extracting) 或“得到”(getting) 。>> 常称为“提
取运算符”。
2、cin 要与 >> 配合使用。例如:
3、C++为流输入输出提供了格式控制,如:dec(用十进制形式),hex(用十六进制
形式),oct(用八进制形式), 还可以控制实数的输出精度等。
14.5 函数的重载
1、C++允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和
参数类型不同,而且函数类型也可不同,这就是函数的重载,即一个函数名多用。
2、系统会根据参数的类型和个数找到与之匹配的函数,并调用不同的函数。
14.6 带缺省参数的函数
C++允许实参个数与形参个数不同。办法是在形参表列中对一个或几个形参指定
缺省值(或称默认值)。
例如某一函数的首部可用如下形式:
void fun(int a, int b, int c=100)
在调用此函数时如写成 fun(2,4,6),则形参 a,b,c 的值分别为 2,4,6(这是
与过去一样的)。如果写成 fun(2,4) ,即少写了最后一个参数,由于在函数定义时已
指定了 c 的缺省值为 100,因此 a,b,c 的值分别为 2,4,100。请注意:赋予缺省值
的参数必须放在形参表列中的最右端。例如:
void f1(float a, int b, int c=0, char d=′a′) (正确)
void f2(float a, int c=0, char d=′a′, int b) (不正确)
注意:不要同时使用重载函数和缺省参数的函数,因为当调用函数时少写一个参
数,系统无法判定是利用重载函数还是利用缺省参数的函数,会发生错误。
14.7 变量的引用类型
1、“引用”(reference)是 C++的一种新的变量类型,是对 C 的一个重要扩充。它的
作用是为一个变量起一个别名。
2、假如有一个变量 a,想给它起一个别名 b,可以这样写:
int a;
int &b=a;
这就声明了 b 是 a 的“引用”,即 a 的别名。经过这样的声明后,使用 a 或 b 的作
用相同,都代表同一变量。注意:在上述声明中,&是“引用声明符”, 并不代表地址。
不要理解为“把 a 的值赋给 b 的地址”。
3、声明引用并不另开辟内存单元,b 和 a 都代表同一变量单元。在声明一个引用
型变量时,必须同时使之初始化,即声明它代表哪一个变量。 在声明一个变量的引
用后,
4、在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变
量的别名。下面的用法不对:
int a1,a2;
int &b=a1;
int &b=a2;(企图使 b 变成 a2 的引用(别名)是不行的)
5、C++之所以增加“引用”,主要是把它作为函数参数,以扩充函数传递数据的功
能。 C++提供了向函数传递数据的第三种方法,即传送变量的别名。例如:
#include <iostream.h>
void swap(int &a, int &b)
{int temp;
temp=a;
a=b;
b=temp;
}
void main( )
{int i=3,j=5;
swap(i, j);
cout<<“i=”<<i<<"
"<<“j=”<<j<<endl;
}在 swap 函数的形参表列中声明变量 a 和 b 是整型的引用变量(和其他变量一样,
既可以在函数体中声明变量的类型,也可以在定义函数时在形参表列中声明变量的类
型)。
请注意:在此处&a 不是“a 的地址”,而是指“a 是一个引用型变量”。 但是此时并
未对它们初始化,即未指定它们是哪个变量的别名。当 main 函数调用 swap 函数时由
实参把变量名传给形参。i 的名字传给引用变量 a,这样 a 就成了 i 的别名。同理,b
成为 j 的别名。a 和 i 代表同一个变量,b 和 j 代表同一个变量。在 swap 函数中使 a 和
b 的值对换,显然,i 和 j 的值同时改变了。
当读者看到&a 这样的形式时,怎样区别是声明引用变量还是取地址的操作呢?请
记住,当&a 的前面有类型符时(如 int &a),它必然是对引用的声明;如果前面无类
型符(如&a),则是取变量的地址。
14.8 内置函数
调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,
从而降低程序的执行效率。C++提供一种提高效率的方法,即在编译时将所调用函数
的代码嵌入到主调函数中。这种嵌入到主调函数中的函数称为内置函数(inline
function),又称内嵌函数。
例如:
#include <iostream.h>
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!