s_linux C 编程基础

linux 下进行C编程基础

Table of Contents

  • 1. 源程序的编译
  • 2. 简单Makefile 的编写
  • 3. 程序库的链接
  • 4. 程序的调试
  • 5. 头文件和系统求助

1 源程序的编译

在linux 下,如果要编译一个C源程序,我们要使用 GNU 的gcc 编译器。 下面我们以一个例子说明如何使用 gcc 编译器。 如下代码示:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("hello world!\n");
}

要编译这个程序,我们只要在命令行中执行:

$ gcc hello.c -o hello

gcc编译器就会为我们生成一个hello的可执行文件,执行./hello 就可以看到 程序的输出结果。命令行中gcc 表示我们是用gcc 来编译我们的源程序,-o 选项表示我们要求编译器输出可执行文件 hello, hello.c 是我们的源程序。

gcc 的 -c 选项表示我们只要求编译器输出目标代码 gcc 的 -g 选项表示我们要求编译器在编译的时候提供我们以后对程序进行调试的信息

2 简单Makefile 的编写

假设我们有下面这样一个程序,源码如下:

// main.c
#include "s1.h"
#include "s2.h"

int main(int argc, char **argv)
{
    s1_print("hello");
    s2_print("hello");

    return 0;
}
// s1.h
#ifndef _S_1_H
#define _S_1_H

void s1_print(char *str);

#endif // _S_1_H
// s1.c
#include <stdio.h>

#include "s1.h"

void s1_print(char *str)
{
    printf("s1 print %s\n", str);
}
// s2.h
#ifndef _S_2_H
#define _S_2_H

void s2_print(char *str);

#endif // _S_2_H
// s2.c
#include <stdio.h>

#include "s2.h"

void s2_print(char *str)
{
    printf("s2 print %s\n", str);
}

当然由于这个程序很短,我们可以这样来编译

$ gcc -c main.c
$ gcc -c s1.c
$ gcc -c s2.c
$ gcc -o main main.o s1.o s2.o

这样的话,我们也可以产生main程序,而且也不是很麻烦,但是如果我们考虑一下,如果 有一天我们修改了其中的一个文件(比如s1.c) 那么我们难道还要重新输入上面的命令? 写一个shell 脚本,让她帮我去完成不就可以了。是的,对于这个程序来说,是可以起到 作用的。但是当我们把事情想的更复杂一些,如果我们的程序有几百个源程序的时候,难 道也要编译器重新一个一个的去编译?

为些,聪明的程序员我们想出了一个很好的工具来做这件事情,这就是make.我们只要 执行一下make,就可以把上面的问题解决。在我们执行make之前,我们要先编写一个 非常重要的文件,Makefile,对于上面的那个程序来说,可能的一个Makefile 文件是:

# Makefile
main: main.o s1.o s2.o
    gcc -o main main.o s1.o s2.o

main.o: main.c s1.h s2.h
    gcc -c main.c

s1.o: s1.c s1.h
    gcc -c s1.c

s2.o: s2.c s2.h
    gcc -c s2.c

有了这个Makefile 文件,不管我们什么时候个性了源程序当中的什么文件,我们只要 执行make命令,我们的编译器都只会去编译与我们修改的及其相关的文件,其它的文件 她理都不去理。

下面学习Makefile 是如何编写的,在Makefile中#开始的都是注释行。Makefile中最重 要的是描述文件的依赖关系的说明。一般的格式是:

target: components
TAB rule

第一行表示的是信赖关系,第二行是规则。 比如我们上面的那个Makefile文件的

main: main.o s1.o s2.o

表示我们的目标(target) main 的信赖对象(components)是 main.o s1.o s2.o 当依赖的对象在目标修改以后的时间有修改的话,就要去执行规则行中指定的命令, 就像我们上面那个

gcc -o main main.o s1.o s2.o

注意规则一行中的TAB表示那里是一个TAB键。

Makefile有三个非常有用的变量,分别是[email protected], $^, $< 分别代表的意思是:

[email protected] 目标文件
$^ 所有依赖文件
$< 第一个依赖的文件

如果我们使用上面三个变量,那么我们可以简化我们的Makefile文件为:

main: main.o s1.o s2.o
    gcc -o $@ $^

main.o: main.c s1.h s2.h
    gcc -c $<

s1.o: s1.c s1.h
    gcc -c $<

s2.o: s2.c s2.h
    gcc -c $<

简化以后,我们的Makefile 是简单了一些。不过人们有时还想更简单一些。这里 我们学习一个Makefile 的缺省规则

.c.o:
TAB gcc -c $<

这个规则表示所有的.o 文件都是依赖于相应的.c文件的。比如s1.o 依赖于s1.c。 这样 Makefile 还可以写成:

main: main.o s1.o s2.o
    gcc -o $@ $^
.c.o:
    gcc -c $<

3 程序库的链接

对于一前常用的函数实现,gcc 编译器会自动去连接一些常用库。这样我们就没必要 自己去指定了。有时候我们在编译程序的时候还要指定库的路径。这个时候我们要用到 编译器的 -L 选项指定路径。比如说我们有一个库在 /home/xx/slib 下,这样我们 编译的时候还要加上 -L /home/xx/slib 对于一些标准库来说,我们没有必要指出路径,只要它们在缺省库的路径下就可以。 系统的缺省库的路径是 /lib /usr/lib /usr/local/lib 在这三个路径下面的库,我们可以不指定路径。

4 程序的调试

我们编写的程序不太可能一次性成功,使用 gcc 编译时加 -g 选项,然后 使用 gdb 进行调试。

5 头文件和系统求助

如果我们要查看write 这个函数的说明,当我们执行 man write 时,输出的结果 却不是我们所需要的。因为我们要的是 write 这个函数的说明,可是出来的却是这个 命令的说明。为了得到 write 的函数说明我们要用 man 2 write ,2表示我们用的 write 这个函数是系统调用函数,还有一个我们常用的是3,表示的函数是C库函数。

Created: 2015-07-25 Sat 00:04

Emacs 24.4.1 (Org mode 8.3beta)

Validate

时间: 2024-10-24 04:44:09

s_linux C 编程基础的相关文章

1.5编程基础之循环控制_29:数字反转

/* 1.5编程基础之循环控制 29:数字反转 总时间限制: 1000ms 内存限制: 65536kB 描述 给定一个整数,请将该数各个位上数字反转得到一个新数. 新数也应满足整数的常见形式,即除非给定的原数为零, 否则反转后得到的新数的最高位数字不应为零(参见样例2). 输入 输入共 1 行,一个整数N. -1,000,000,000 ≤ N≤ 1,000,000,000. 输出 输出共 1 行,一个整数,表示反转后的新数. 样例输入 样例 #1: 123 样例 #2: -380 样例输出 样

网络编程基础

网络编程基础 1.套接字概念 Linux环境下使用套接字进行进程之间的通信.用过套接字的接口,其他进程的位置对于应用程序来讲是透明的.相互通信双方端点都有一个套接字,双方如果要进行通信,通过套接字建立桥梁,双方就可以通信了. 类似文件一样,套接字也有一个套接字描述符,应用程序可以像操作文件一样操作套接字.在进行网络通信的过程中,用户感觉就是在操作文件一样,这是Linux将外部设备抽象为一个文件的好处. 2.字节序 不同主机的体系结构不同,所采用的数据存储方式不同.网络中,进程之间的通信是跨主机的

多线程编程基础知识

多线程编程基础知识 http://www.cnblogs.com/cy163/archive/2006/11/02/547428.html 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.因此掌握

shell 脚本编程基础

一.编程基础 程序:指令+数据 程序编程风格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 shell程序:提供了编程能力,解释执行 1.程序的执行方式 计算机:运行二进制指令: 编程语言: 低级:汇编 高级: 编译:高级语言–>编译器–>目标代码 java,C# 解释:高级语言–>解释器–>机器代码 shell, perl, python 2.编程基本概念 编程逻辑处理方式: 顺序执行 循环执行 选择执行 shell编程:过程式.解释执行 编程语言

DAY9:bash脚本编程基础(1)

内容主要为: 一.编程基础 二.shell脚本及其基本格式 三.变量 四.运算 五.条件测试 六.流程控制 一.编程基础 1)程序 程序:指令+数据 程序编程风格: 过程式:以指令为中心,数据服务于指令(C,bash) 对象式:以数据为中心,指令服务于数据 (java,C++,Python) shell程序:提供了编程能力,解释执行 2)程序的执行方式 计算机:运行二进制指令: 编程语言: 低级:汇编 高级: 编译:高级语言-->编译器-->目标代码 java,C# 解释:高级语言-->

iOS开发网络篇—网络编程基础

iOS开发网络篇—网络编程基础 一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过网络跟外界进行数据交互.数据更新,应用才能保持新鲜.活力 (3)如果没有了网络,也就缺少了数据变化,无论外观多么华丽,终将变成一潭死水 移动网络应用 = 良好的UI + 良好的用户体验 + 实时更新的数据 新闻:网易新闻.新浪新闻.搜狐新闻.腾讯新闻 视频:优酷.百度视频.搜狐视频.爱奇艺视频 音乐

LINQ to XML 编程基础

1.LINQ to XML类 以下的代码演示了如何使用LINQ to XML来快速创建一个xml: 隐藏行号 复制代码 ?创建 XML public static void CreateDocument() { string path = @"d:\website"; XDocument xdoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), new XEle

Java网络编程基础(六)— 基于TCP的NIO简单聊天系统

在Java网络编程基础(四)中提到了基于Socket的TCP/IP简单聊天系统实现了一个多客户端之间护法消息的简单聊天系统.其服务端采用了多线程来处理多个客户端的消息发送,并转发给目的用户.但是由于它是基于Socket的,因此是阻塞的. 本节我们将通过SocketChannel和ServerSocketChannel来实现同样的功能. 1.客户端输入消息的格式 username:msg    username表示要发送的的用户名,msg为发送内容,以冒号分割 2.实现思路 实现思路与Java网络

LINUX下C语言编程基础

实验二 Linux下C语言编程基础 一.实验目的 1. 熟悉Linux系统下的开发环境 2. 熟悉vi的基本操作 3. 熟悉gcc编译器的基本原理 4. 熟练使用gcc编译器的常用选项 5 .熟练使用gdb调试技术 6. 熟悉makefile基本原理及语法规范 7. 掌握静态库和动态库的生成 二.实验步骤 1. 快捷键 Ubuntu中: 2. vim VIM是一个非常好的文本编辑器,很多专业程序员使用VIM编辑代码,即使以后你不编写程序,只要跟文本打交道,都应该学学VIM,可以浏览参考一下普通人