龙空技术网

linux操作系统下c编程入门开发工具介绍——实战学习

Linux特训营 1014

前言:

此时看官们对“for里面嵌套if然后else怎么不用对齐if也行”大概比较重视,同学们都需要了解一些“for里面嵌套if然后else怎么不用对齐if也行”的相关知识。那么小编在网摘上汇集了一些关于“for里面嵌套if然后else怎么不用对齐if也行””的相关资讯,希望各位老铁们能喜欢,同学们快快来了解一下吧!

Linux程序设计基础知识

对一个Linux开发人员来说,在使用一种编程语言编写程序以前,对操作系统中程序的保存位置有一个透彻的了解是很重要的。比如,应知道软件工具和开发资源保存在什么位置是很重要的。下面首先简单介绍Linux的几个重要的子目录和文件。

这部分内容虽然是针对 Linux的,但同样也适用于其他类UNIX系统。

1.3.1 程序安装目录

Linux下的程序通常都保存在专门的目录里。系统软件可以在/usr/bin子目录里找到。系统管理员为某个特定的主机系统或本地网络添加的程序可以在/usr/local/bin子目录里找到。

系统管理员一般都喜欢使用/usr/local子目录,因为它可以把供应商提供的文件和后来添加的程序以及系统本身提供的程序隔离开来。/usr子目录的这种布局方法在需要对操作系统进行升级的时候非常有用,因为只有/usr/local子目录里的东西需要保留。我们建议读者编译自己的程序时,按照/usr/local子目录的树状结构来安装和访问相应的文件。

某些随后安装的软件都有它们自己的子目录结构,其执行程序也保存在特定的子目录里,最明显的例子就是 X窗口系统,它通常安装在一个名为/usr/X11R6的子目录里,XFree论坛组织发行的用于英特尔处理器芯片的各种XFree 86窗口系统变体也安装在这里。

GNU的C语言编译器gcc(后面的程序设计示例中使用的就是它)通常安装在/usr/bin或者/usr/local/bin子目录里,但通过它运行的各种编译器支持程序一般都保存在另一个位置。这个位置是在用户使用自己的编译器时指定的,随主机类型的不同而不同。对 Linux系统来说,这个位置通常是/usr/lib/gcc-lib/目录下以其版本号确定的某个下级子目录。GN的C/C++编译器的各种编译程序以及GNU专用的头文件都保存在这里。

1.3.2 头文件

在使用C语言和其他语言进行程序设计的时候,我们需要头文件来提供对常数的定义和对系统及库函数调用的声明。对C语言来说,这些头文件几乎永远保存在/usr/include及其下级子目录里。那些赖于所运行的 UNIX或Linux操作系统特定版本的头文件一般可以在/usr/include/sys或/usr/include/linux子目录里找到。其他的程序设计软件也可以有一些预先定义好的声明文件,它们的保存位置可以被相应的编译器自动查找到。比如,X窗口系统的/usr/include/X1R6子目录和GNU C++编译器的/usr/include/g++ -2子目录等。

在调用C语言编译器的时候,可以通过给出“ -I”编译命令标志来引用保存在下级子目录或者非标准位置的头文件,类似命令如下:

[david@localhost linux]$ gcc -I /usr/openwin/include hello.c

该命令会使编译器在/usr/openwin/include子目录和标准安装目录两个位置查找fred.c程序里包含的头文件。具体情况可以参考第3章。

用grep命令来查找含有某些特定定义与函数声明的头文件是很方便的。假设想知道用来返回程序退出状态的文件的名字,可以使用如下方法:

先进入/usr/include子目录,然后在grep命令里给出该名字的几个字母,如下所示:

[david@localhost linux]$ grep KEYSPAN *.h

pci_ids.h:#define PCI_SUBVENDOR_ID_KEYSPAN 0x11a9

pci_ids.h:#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334

grep命令会在该子目录里所有名字以.h结尾的文件里查找字符串“KEYSPAN”。在上面的例子里,(从其他文件中间)可以查找到文件pci_ids.h。

1.3.3 库文件

库文件是一些预先编译好的函数的集合,那些函数都是按照可再使用的原则编写的。它们通常由一组互相关联的用来完成某项常见工作的函数构成。比如用来处理屏幕显示情况的函数(curses库)等。我们将在后续章节讲述这些函数库文件。

标准的系统库文件一般保存在/lib或者/usr/lib子目录里。编译时要告诉 C语言编译器(更确切地说是链接程序)应去查找哪些库文件。默认情况下,它只会查找 C语言的标准库文件。这是从计算机速度还很慢、CPU价格还很昂贵的年代遗留下来的问题。在当时,把一个库文件放到标准化子目录里然后寄希望于编译器自己找到它是不实际的。库文件必须遵守一定的命名规则,还必须在命令行上明确地给出来。

库文件的名字永远以lib这几个字母打头,随后是说明函数库情况的部分(比如用c表示这是一个 C语言库;而m表示这是一个数学运算库等)。文件名的最后部分以一个句点(.)开始,然后给出这个库文件的类型,如下所示:

● .a 传统的静态型函数库。

● .so和. sa 共享型函数库(见下面的解释)。

函数库一般分为静态和共享两种格式,用ls /usr/lib命令查一下就能看到。在通知编译器查找某个库文件的时候,既可以给出其完整的路径名,也可以使用–l标志。详细内容可以参考第3章。

1. 静态库

函数库最简单的形式就是一组处于可以“拿来就用”状态下的二进制目标代码文件。当有程序需要用到函数库中的某个函数时,就会通过 include语句引用对此函数做出声明的头文件。编译器和链接程序负责把程序代码和库函数结合在一起成为一个独立的可执行程序。如果使用的不是标准的C语言运行库而是某个扩展库,就必须用–l选项指定它。

静态库也叫做档案(archive),它们的文件名按惯例都以. a结尾。比如 C语言标准库为/usr/lib/libc.a、X11库为/usr/X11R6/lib/libX11.a等。

自己建立和维护静态库的工作并不困难,用ar(“建立档案”的意思)程序就可以做到,另外要注意的是,应该用gcc -c命令对函数分别进行编译。应该尽量把函数分别保存到不同的源代码文件里去。如果函数需要存取普通数据,可以把它们放到同一个源代码文件里并使用在其中声明为static类型的变量。

2. 共享库

静态库的缺点是,如果我们在同一时间运行多个程序而它们又都使用着来自同一个函数库里的函数时,内存里就会有许多份同一函数的备份,在程序文件本身也有许多份同样的备份。这会消耗大量宝贵的内存和硬盘空间。

许多UNIX系统支持共享库,它同时克服了在这两方面的无谓消耗。对共享库和它们在不同系统上实现方法的详细讨论超出了本书的范围,所以我们把注意力集中在眼前 Linux环境下的实现方法上。

共享库的存放位置和静态库是一样的,但有着不同的文件后缀。在一个典型的 Linux系统上,C语言标准库的共享版本是 /usr/lib/libc.so N,其中的N是主版本号。

Linux下C语言编程环境概述

Linux下C语言编程常用的编辑器是vim或emacs,编译器一般用gcc,编译链接程序用make,跟踪调试一般使用gdb,项目管理用makefile。下面先通过一个小程序来熟悉这些工具的基本应用。各个工具的详细使用方法将在后面的各个章节逐步讲解。

(1) 要编辑C源程序,应首先打开vim或emacs编辑器,然后录入以下多段源代码。使用main函数调用mytool1_print、mytool2_print这两个函数。

#include "mytool1.h"

#include "mytool2.h"

int main(int argc,char **argv)

{

mytool1_print("hello");

mytool2_print("hello");

}

(2) 在mytool1.h中定义mytool1.c的头文件。

/* mytool1.h */

#ifndef_MYTOOL_1_H

#define_MYTOOL_1_H

void mytool1_print(char *print_str);

#endif

(3) 用mytool1.c实现一个简单的打印显示功能。

/* mytool1.c */

#include "mytool1.h"

void mytool1_print(char *print_str)

{

printf("This is mytool1 print %s/n",print_str);

}

(4) 在mytool2.h中定义mytool2.c头文件。

/* mytool2.h */

#ifndef _MYTOOL_2_H

#define _MYTOOL_2_H

void mytool2_print(char *print_str);

#endif

(5) mytool2.c实现的功能与mytool1.c相似。

/* mytool2.c */

#include "mytool2.h"

void mytool2_print(char *print_str)

{

printf("This is mytool2 print %s/n",print_str);

}

(6) 使用makefile文件进行项目管理。makefile文件内容如下。

main:main.o mytool1.o mytool2.o

gcc -o main main.o mytool1.o mytool2.o

main.o:main.c mytool1.h mytool2.h

gcc -c main.c

mytool1.o:mytool1.c mytool1.h

gcc -c mytool1.c

mytool2.o:mytool2.c mytool2.h

gcc -c mytool2.c

(7) 将源程序文件和makefile文件保存在Linux下的同一个文件夹下,然后运行make编译链接程序如下:

[david@localhost 1c]$ make

[david@localhost 1c]$ ./main

This is mytool1 print hello

This is mytool2 print hello

Linux程序设计的特点

在进行程序设计时首先应养成良好的程序设计风格。Linux操作系统的设计师们鼓励人们采用一种独到的程序设计风格。下面是Linux程序和系统所共有的一些特点。

(1) 简单性。许多最有用的 Linux软件工具都是非常简单的,程序小而易于理解。

(2) 重点性。一个所谓功能齐全的程序可能既不容易使用,也不容易维护。如果程序只用于一个目的,那么当更好的算法或更好的操作界面被开发出来的时候,它就更容易得到改进。在 Linux世界里,通常会在需求出现的时候把小的工具程序组合到一起来完成一项更大的任务,而不是用一个巨大的程序预测一个用户的需求。

(3) 可反复性。使用的程序组件把应用程序的核心部分组建成一个库。带有简单而又灵活的程序设计接口并且文档齐备的函数库能够帮助其他人开发同类的项目,或者能够把这里的技巧用在新的应用领域。例如dbm数据库函数库就是一套由不同功能的函数组成的集合,而不是一个单一的数据库管理系统。

(4) 过滤性。许多Linux应用程序可以用作过滤器,即它们可以把自己的输入转换为另外一种形式的输出。在后面将会讲到,Linux提供的工具程序能够将其他Linux程序组合成相当复杂的应用软件,其组合方法既新颖又奇特。当然,这类程序组合正是由Linux独特的开发方法支撑着的。

(5) 开放性。文件格式比较成功和流行的 Linux程序所使用的配置文件和数据文件都是普通的 ASCII文本。如果在程序开发中遵循该原则,将是一种很好的做法。它使用户能够利用标准的软件工具对配置数据进行改动和搜索,从而开发出新的工具,并通过新的函数对数据文件进行处理。源代码交叉引用检查软件 ctags就是一个这样的好例子,它把程序中的符号位置信息以规则表达式的形式记录下来供检索程序使用。

(6) 灵活性。因为你根本无法预测一个不太聪明的用户会怎样使用你的程序,因此在进行程序设计时,要尽可能地增加灵活性,尽量避免给数据域长度或者记录条数加上限制。同时如果可能,应尽量编写能够响应网络访问的程序,使它既能够跨网络运行又能够在本地单机上运行。

Linux下C语言编码的风格

Linux作为GN家族的一员,其源代码数以万计,而在阅读这些源代码时我们会发现,不同的源代码的美观程度和编程风格都不尽相同,例如下面的glibc代码:

static voidrelease_libc_mem (void)

{

/*Only call the free function if we still are running in mtrace mode. */

if (mallstream != NULL)

__libc_freeres ();

}

或者Linux的核心代码:

static int do_linuxrc(void * shell)

{

static char *argv[] = { "linuxrc",NULL,};

close(0);close(1);close(2);

setsid();

(void) open("/dev/console",O_RDWR,0);

(void) dup(0);

(void) dup(0);

return execve(shell,argv,envp_init);

}

比较一下,上面的这些代码是否看起来让人赏心悦目?而有些程序员编写的程序由于没有很好的缩进及顺序,让人看起来直皱眉头。编写干净美观的代码,不仅仅使代码更容易阅读,还能使代码成为一件艺术品。与微软的匈牙利命名法一样,Linux上的编程主要有两种编程风格:GNU风格和Linux核心风格,下面将分别介绍。

1.6.1 GNU编程风格

下面是基于GNU的编程风格,编写代码时应遵循这些基本要求。

● 函数开头的左花括号放到最左边,避免把任何其他的左花括号、左括号或者左方括号放到最左边。

à 尽力避免让两个不同优先级的操作符出现在相同的对齐方式中。

à 每个程序都应该有一段简短地说明其功能的注释开头。例如:fmt - filter for simplefilling of text。

● 请为每个函数书写注释,以说明函数做了些什么,需要哪些种类的参数,参数可能值的含义以及用途。

à 不要在声明多个变量时跨行。在每一行中都以一个新的声明开头。

à 当在一个if语句中嵌套了另一个if-else语句时,应用花括号把if-else括起来。

● 要在同一个声明中同时说明结构标识和变量,或者结构标识和类型定义(typedef)。

à 尽力避免在if的条件中进行赋值。

à 请在名字中使用下划线以分隔单词,尽量使用小写; 把大写字母留给宏和枚举常量,以及根据统一的惯例使用的前缀。

à 命令一个命令行选项时,给出的变量应该在选项含义的说明之后,而不是选项字符之后。

1.6.2 Linux 内核编程风格

下面是 Linux 内核所要求的编程风格:

● 注意缩进格式。

● 将开始的大括号放在一行的最后,而将结束大括号放在一行的第一位。

● 命名系统。变量命名尽量使用简短的名字。

● 函数最好要短小精悍,一个函数最好只作一件事情。

● 注释。注释说明代码的功能,而不是说明其实现原理。

看了上面两种风格的介绍,读者是不是觉得有些太多了,难以记住?不要紧,Linux有很多工具来帮助我们。除了vim和emacs以外,还有一个非常有意思的小工具 indent可以帮我们美化C/C++源代码。

下面用这条命令将Linux 内核编程风格的程序quan.c转变为 GNU编程风格,代码如下:

[david@localhost ~]$ indent -gnu quan.c

利用indent这个工具,大家就可以方便地写出漂亮的代码来。

LinuxC编程工具介绍

在实际的开发中,C语言代码除了符合最基本的语法规范之外还必须符合设计者的逻辑意图,如果发现生成的可执行文件运行结果不正确,则可以通过相应的调试环境来跟踪调试,因此需要用到gdb

一.GDB篇gdb基本命令

使用

1.调用gdb一般只需要一个参数

gdb <可执行文件名>1

2.一旦调试的程序出现错误,会在当前目录下产生核心内存映像core文件,可以在调用时指定一个core文件

gdb <可执行文件名> core1

3.制定进程号的执行方式

gdb <可执行的文件名> <进程号>1

3.应用实例

二.项目管理工具make1.简单是实例

1).新建一个hello.c

2).新建一个hello.h

//这里不做任何操作

void m();

1

2

3).编译makefile文件

#这里写注释

#命令行前面必须加table空格

hello:hello.c hello.h

gcc -o hello hello.c hello.h

1

2

3

4

5

6

4.接下来进行管理

lancao@lancao:~$ make //直接输入make命令,会根据makefile文件信息进行执行文件

gcc -o hello hello.c hello.h //系统执行的语句

lancao@lancao:~$ ls

hello hello.c hello.h makefile //目标文件生成

2.接下来我们看一个稍微复杂一点的makefile

二.makefile中的变量

(1)Makefile中的 符号的意思:

  $@ 表示目标文件

  $^ 表示所有的依赖文件

  $< 表示第一个依赖文件

  $? 表示比目标还要新的依赖文件列表

1

2

3

4

(2)wildcard、notdir、patsubst的意思:

  wildcard : 扩展通配符

  notdir : 去除路径

  patsubst :替换通配符

 

1

2

3

4

autotools自动生成makefile文件

关注+后台私信;资料;两个字可以免费领取 资料内容包括:C/C++,Linux,golang,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,嵌入式 等。。。

标签: #for里面嵌套if然后else怎么不用对齐if也行 #linux c开发工具