搭建环境

# 安装C/C++的编译工具包,包括gcc与make等工具.使用`$ apt depends build-essential`查看该包详情
$ sudo apt-get install build-essential
#[可选安装包]简化Debian软件包维护者的工作的脚本工具
sudo apt-get install  devscripts equivs
#[可选安装包]安装多重库。既能编译32位的目标对象,又能编译64位的目标对象;
$ sudo apt-get install gcc-multilib g++-multilib
#[可选安装包]安装模块助手包,编译Linux内核模块需要;
$ sudo apt-get install module-assistant

sudo apt-get install gcc-10 g+±10
ENV CC=gcc-10 AR=gcc-ar-10 NM=gcc-nm-10 RANLIB=gcc-ranlib-10
CFLAGS=“-pipe -O3 -march=native”

编译器(GCC)

常用选项
$ gcc -S -masm=intel sample.c -o sample.s
# 编译动态库
gcc test1.c test2.c -shared -fPIC -o libtest.so
# 使用动态库
gcc main.c -L. -ltest -o a.out
# -L : 表示需要库的路径
# -l:表示需要库的名称,如libtest.so,名称则为test
# 编译静态库
gcc -c test1.c test2.c
ar -r libtest.a test1.o test2.o
# 使用静态库
gcc main.c -static -L. -ltest -o a.out  
选项 含义
-v 查看gcc编译器的版本,显示gcc执行时的详细过程;
-o 指定输出文件名为file,这个名称不能跟源文件名同名;
-E 只预处理,不会编译、汇编、链接;
-S 只编译,不会汇编、链接;
-c 编译可重定位文件(REL);
–static 链接静态库,如果不使用这个参数,而静态库与动态库同名的话,会优先使用动态库
-shared 生成一个共享对象,然后可以与其他对象链接对象以形成可执行文件。并不是所有的系统都支持这一点选择,还需指定相同的内容用于生成代码的选项集’ -fpic’。即使不加fPIC也可以生成.so文件,但是对于源文件有要求,因为不加fPIC编译的so必须要在加载到用户程序的地址空间时重定向所有表目,所以在它里面不能引用其它地方的代码
-fPIC 产生位置无关代码(Position-Independent Code),不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位
-g 产生调试工具(GNU的gdb)所必要的符号信息,想要对源代码进行调试,就必须加入这个选项;
-m32 编译出32位目标文件;
-masm=intel 输出intel格式汇编;默认是输出AT&T格式汇编
-std 指定c语言标准,默认ANSI
-M 自动找寻源文件中包含的头文件
-MM 自动找寻源文件中包含的头文件,不包括系统头文件
-I 指定自动检索头文件的目录
-include 指定头文件,一般情况在代码文件中#include(尖括号系统默认路径,引号当前目录优先)头文件
-L 指定库文件所在的目录
-l 指定库,参数紧接着就是库名(不是库路径,库的路径可能是-L指定或系统默认的库路径)
-Wl 告诉编译器将后面的参数传递给链接器,多个参数用逗号分开
-On 优化编译 n为等级,调试的时候最好不使用任何优化选项
-march=native 相当于LLVM的rustc或swiftc
-mcpu=type CPU指令,type可为i386、i486、pentium及i686等
-mieee-fp 使用IEEE标准进行浮点数的比较
-mno-ieee-fp 不使用IEEE标准进行浮点数的比较
-msoft-float 输出包含浮点库调用的目标代码
-mshort 把int类型作为16位处理,相当于short int
-mrtd 强行将函数参数个数固定的函数用ret NUM返回,节省调用函数的一条指令
-ansi 支持符合ANSI标准的C程序
-pedantic 允许发出ANSI C标准所列的全部警告信息
-pedantic-error 允许发出ANSI C标准所列的全部错误信息
-w 关闭所有告警
-Wall 允许发出Gcc提供的所有有用的报警信息
-Werror 把所有的告警信息转化为错误信息,并在告警发生时终止编译过程
环境变量
  • $CC:用来指定c编译器。
  • $CPP:该环境变量是c=语言程序的预处理器
  • $CPPFLAGS:该环境变量是传递给C预处理器
  • $CFLAGS:该环境变量是传递给c语言程序的编译器选项,同–cflags选项。例如有一个头文件在非标准目录
  • $LD_LIBRARY_PATH:加载器库目录
CFLAGS=-I/path/to/include //(大写的i)

上行设置可传递给c编译器,当其在标准目录中找不到头文件时,使其到/path/to/include目录中去寻找

连接器(ld)

GNU程序链接器(The GNU linker) 详情可以通过 man ld查阅。

环境变量

LIBS:传递给连接器的选项,同-libs选项。例如告诉链接器要链接哪些库文件。 -l,例如:-lm 表示程序指定的链接库名是m,-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。
LDFLAGS:传递给连接器的选项。例如告诉链接器从哪里寻找库文件 -L
如果库文件没放在/lib和/usr/lib和/usr/local/lib这三个目录里,而是位于非标准的库路径,那就需要告诉连接器到哪一个目录下去链接该库。比如我们把libtest.so放在/path/to/library目录下,那链接参数就是

LDFLAGS=-L/path/to/library -ltest

有时候LDFLAGS指定-L虽然能让链接器找到库进行链接,但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,那么我们需要增加这两个库给"-Wl,R":

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib

链接阶段查询库文件

ld.so通过依次读取

  1. -rpath连接器选项,rpath链接选项主要有两个功能:
  • 程序运行时,优先到rpath指定的目录去寻找依赖库,因为连接器将其指定的路径编码到目标文件中了。
  • 程序链接时,用于指定间接引用的库位置,链接时作用等同且优先于-Wl,-rpath-link

通过readelf查看被硬编码的-rpath:

$ readelf -d <可执行文件名>           # Display the dynamic section (if present)

通过ldd命令查看共享库文件依赖

$ ldd /bin/ls                       # Print shared object dependencies
  1. -rpath-link连接器选项,指定的目录只在链接阶段生效(链接器没有将库的路径包含进目标文件中)
    程序链接时使用-Wl,-rpath-link ,用于指定间接引用的库位置。比如链接a库,a库依赖b库和c库,此场景下,a为直接引用, b和c为间接引用,编译程序时必须显式指定的指定间接引用:
gcc -o test test.c -I. -L. -la -lb -lc

使用 --rpath-link,即可避免显式的指定间接引用:

gcc -o test test.c -I. -L. -la -Wl,-rpath=.
  1. LD_RUN_PATH连接器环境变量
  2. -L 选项,用于指定链接库时的搜索路径目录
  3. 默认的库文件目录/lib、/usr/lib/gcc/ 和/usr/lib/

运行阶段查询库文件:

  1. etc/ld.so.cache
  2. /etc/ld.so.conf

动态链接库的配置工具管理ldconfig
在系统库文件默认目录/lib和/usr/lib以及动态库配置文件/etc/ld.so.conf中搜索出可共享的动态链接库(格式如lib*.so*),生成动态装入程序(ld.so)所需的连接和缓存文件。
缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表
ldconfig -p :打印当前缓存所保存的所有库的名字

编译实用工具pkg-config

在编译时需要包含头文件,链接时需要库文件,但安装一些第三方库之后不知道对应的include文件和lib文件的位置,此时就需要用到pkg-config这个实用工具程序。pkg-config 通过/usr/lib目录与PKG_CONFIG_PATH环境变量定义的目录下的所有*.pc文件来提供如下信息:

  1. C/C++编译器需要的输入参数;
  2. 链接器需要的输入参数;
  3. 已安装软件包的版本信息。

使用示例:

pkg-config --list-all
# 输出pkg-config可列出信息的库
gcc -o test test.c `pkg-config --libs --cflags glib-2.0`
# --libs 输出库文件项
# --cflags 输出头文件项
环境变量
  • $PKG_CONFIG 该环境变量是pkg-config 工具程序的所在路径
  • $PKG_CONFIG_PATH 默认是/usr/lib/pkgconfig目录,可以通过该环境变量指定目录。
    pc文件是文本文件,扩展名是.pc,里面定义开发包的安装路径,Libs参数和Cflags参数等。
  • $PKG_CONFIG_LIBDIR
    该环境变量覆盖pkg-config的内置搜索路径的路径

构建工具

cmake
autoconf:用于依据 configure.in生成 configure 脚本。在目录中运行 ./buildconf即可。
automake
make -j $(nproc)

调试

GDB 是Linux 平台下的调试器,可完成如下的调试任务:

  • 设置断点;
  • 监视程序变量的值;
  • 程序的单步执行;
  • 修改变量的值。
命令 含义
set disassembly-flavor intel 设置环境变量,输出intel格式汇编代码;
disass main 查看main函数汇编代码;

示例:查看函数调用

# gdb -ex "set pagination 0" -ex "thread apply all bt" --batch -p 22222
  • --ex 执行后面跟着的GDB命令
  • set paginagtion 0 不使用分页输出
  • thread apply all bt bt 是backtrace的简写,即对所有线程使用backtrace命令
  • --batch 使用批处理模式,在所有的命令执行完成后退出,正确返回0,错误为非0
  • -p 22222 指定attach哪个进程的ID
    详情链接

语言

引号

双引号返回字符串存储后的结果,即将存储后的指针返回。

char * str="a";//将a与'\0'存储后返回指针给变量str
printf("%s\r\n", str);
char * null="\0";
printf("%s\r\n", null);
char * empty="";
printf("%s\r\n", empty);

单引号返回处理前的结果,即将存储之前转换的整形返回。

  char   c='h';printf("%c\r\n", c);int   i='h';printf("%c\r\n", );

错误示例:

  char   c="h";printf("%c\r\n", c);

编译结果

main.c: In function ‘main’:
main.c:13:16: warning: initialization of ‘char’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion]13 |     char   str="h";|                ^~~

双引号可以用转义或单引号括起来的方式打印输出,单引号只能用转义字符来打印。

待整理

/usr/include/elf.h文件定义了ELF 文件头的结构和相关常数,文中的e_type定义了 ELF文件类型,主要有以下几种:

  • 可重定位文件(Relocatable File) 包含代码和数据,可用来连接成可执行文件或共享目标文件,对应于Linux 中的.o ,Windows 的 .obj。

静态库(current ar archive)就是将可重定位文件归档打包

  • 可执行文件(ELF 64-bit LSB executable) 包含了可以直接执行的程序,它的代表就是ELF 可执行文件,他们一般没有扩展名。比如/bin/bash ,Windows 下的 .exe
  • 共享目标文件(ELF 64-bit LSB shared object ) 包含代码和数据,链接器可以使用这种文件跟其他可重定位文件的共享目标文件链接,产生新的目标文件。另外是动态链接器可以将几个这种共享目标文件与可执行文件结合,作为进程映像来运行。对应于Linux 中的 .so,Windows 中的 DLL
  • 核心转储文件(Core Dump File) 当进程意外终止,系统可以将该进程地址空间的内容及终止时的一些信息转存到核心转储文件。 对应 Linux 下的core dump。
    ELF 文件头的结构和相关常数一般定义在了 /usr/include/elf.h 中
gcc ./main.c -L /home/whois/temp/cc/libtest/ -ltest -I/home/whois/temp/cc/libtest/ -Wl,-rpath=/home/whois/temp/cc/libtest/ -o main

预处理语句#include

  • 系统自带的头文件用尖括号括起来,这样编译器会在系统文件目录下查找。
  • 用户自定义的头文件用双引号括起来,编译器首先会在用户目录下查找,然后再到 C的安装目录(Linux 中可以通过环境变量来设定)中查找,最后在系统文件中查找。

cpu_relax()锁一个最典型的要使用pu_relax()锁的场景是忙等待(也就是死循环等一个事情的发生)
while (p->on_cpu)
cpu_relax();
全局变量虽然属于静态存储方式,但并不是静态变量。全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的。有时候,我们希望函数中局部变量的值在函数调用结束之后不会消失,而仍然保留其原值。即它所占用的存储单元不释放,在下一次调用该函数时,其局部变量的值仍然存在,也就是上一次函数调用结束时的值。这时候,我们就应该将该局部变量用关键字 static 声明为“静态局部变量”。

当将局部变量声明为静态局部变量的时候,也就改变了局部变量的存储位置,即从原来的栈中存放改为静态存储区存放。这让它看起来很像全局变量,其实静态局部变量与全局变量的主要区别就在于可见性,静态局部变量只在其被声明的代码块中是可见的。

把依赖的包先给编译一份出来并且装上
$ mk-build-deps -s sudo -i
打包
$ dpkg-buildpackage -uc -us -b -j$(nproc)

标准与规范

  1. K&R” C
  2. ANSI C(c89)
    定义了 C 标准库;
    新的预处理命令和特性;
    函数原型(prototype);
    新关键字:const、volatile、signed;
    宽字符、宽字符串和多字节字符;
    转化规则、声明(declaration)、类型检查的改变。
  3. ISO 采纳了c89成为国际标准ISO/IEC 9899:1990(c90)
  4. C95
    3个新标准头文件:iso646.h、wctype.h、wchar.h;
    一些新的标记(token)和宏(macro);
    一些新的 printf/scanf 系列函数的格式符;
    增加了大量的宽字符和多字节字符函数、常数和类型。
  5. C99
    复数(complex);整数(integer)类型扩展;变长数组;Boolean 类型;非英语字符集的更好支持;浮点类型的更好支持;提供全部类型的数学函数;C++ 风格注释(//)。
  6. C11 标准新引入的特征尽管没 C99 相对 C90 引入的那么多,但是这些也都十分有用,比如:字节对齐说明符、泛型机制(generic selection)、对多线程的支持、静态断言、原子操作以及对 Unicode 的支持。
  7. C17(也被称为为 C18)是于2018年6月发布的 ISO/IEC 9899:2018 的非正式名称,也是目前(截止到2020年6月)为止最新的 C语言编程标准,被用来替代 C11 标准。
    C17 没有引入新的语言特性,只对 C11 进行了补充和修正。

ISO/IEC 9899:2018
MISRA C:2012 Third Edition, First Revision
SEI CERT C Coding Standard
CWE

二进制文件工具

更多工具点击(GNU Binutils)
readelf显示elf格式文件的信息;
hexdump,以各种进制编码的方式呈现二进制文件;
strings打印文件中可打印字符的字符串;
objdump读取可执行文件并将汇编语言指令转储到屏幕或文件;

     $ objdump -d sample.o$objdump -S main.o -S>main.dis

size,查看对象或归档映像时的内存段大小列表
nm,列出二进制目标文件的符号表,包括符号地址、符号类型、符号名等;
file,确定文件类型;
ldd,查看共享对象(动态链接库)依赖关系;
Itrace,显示运行时从库中调用的所有函数;
strace,显示运行时从系统中调用的所有函数;
例如 sudo strace -p <PID>
strace -fvttTyyx -s 4096 -e socket,bind,listen npm run dev
strace -tt -T -e trace=all -p
ar,查看函数库里的详细情况和用多个对象文件生成一个库文件
**trap -lp 与 kill **,信号量管理;
lsof, lsof -p <PID>
hexdump 以十六进制编码显示二进制文件
vim 查看与编辑二进制文件

      #打开二进制文件vim -d ./main#将进制转换到十六进制显示,具体可查看xxd命令:%!xxd -g 2#将十六进制恢复到二进制显示:%!xxd -r#保存:wq!

比较两个二进制文件
vim -bd main1 main2

打开后就可以在两个窗口里面显示两个文件
ctrl + W +L 把输入焦点切换到右边的窗口,激活右边的窗口后输入的命令就是针对右窗口了
:%!xxd -g 1 切换成十六进制的一个字节的模式
ctrl + W +H 把输入焦点切换到左边的窗口
:%!xxd -g 1
] + c 查找上一个不同点
[ + c 查找下一个不同点

hexdump+sed+xxd 三个命令批量替换二进制文件示例

#摘抄于 https://www.zhihu.com/question/19703679
hexdump -ve '1/1 "%.2x"' ora10g_mytab_us7ascii.dmp | sed "s/0001000107d00001/0001035407d00001/" |xxd -r -p > ora10g_mytab_zhs16gbk.dmp

addr2line 将地址转换成文件名与行号

资源链接

  • c语言指导
  • Linux源码在线

Ubuntu系统环境中C语言开发配置备忘笔记相关推荐

  1. 算法导论中C语言代码,算法导论-学习笔记与进度

    算法导论 阅读进度 第一部分 基础知识 第一章 计算中算法的角色 Done 1.1 算法 输入与输出 算法可以解决哪些问题 数据结构 技术 一些比较难的问题 1.2 作为一种技术的算法 效率 算法和其 ...

  2. 树莓派Ubuntu mate中借助OpenCV实现摄像头定时拍照并保存python语言

    刚刚入门的小白,第一次写博客,有不妥的地方还望各路大佬多多指教~ 本帖主要是介绍利用python语言如何在树莓派Ubuntu mate中借助OpenCV实现摄像头给定间隔时间连续拍照,并以拍照时间命名 ...

  3. Ubuntu系统中编写c语言程序教程

    目录 1.准备工作 1.1 安装GCC及必要软件包 2.使用GCC编写C语言程序 2.1 编写一个整型运算反回浮点型的程序 2.2 在windows系统下使用编译工具编译该程序 3.使用Makefil ...

  4. c语言程序打不开如何修复,处理win7中打不开程序修复0xc0000142错误代码的问题

    我们在win7系统的使用中,对于电脑中安装的软件我们很多的时候都是直接通过桌面上的软件来操作打开的吗,但是有的小伙伴遇到在打开的电脑找那个出现软件无法打开的情况,提示错误是此应用无法正常的启动错误代码 ...

  5. ubuntu系统php环境变量设置,Ubuntu系统环境变量详解

    使用Ubuntu 进行开发绕不开的就是环境变量的配置,由于Linux系统严格的权限管理,造成Ubuntu系统有多个环境变量配置文件,如果不了解其调用顺序,很有可能遇到配置了环境变量,而没有其作用的问题 ...

  6. [Ubuntu] Ubuntu系统环境变量详解

    使用Ubuntu 进行开发绕不开的就是环境变量的配置,由于Linux系统严格的权限管理,造成Ubuntu系统有多个环境变量配置文件,如果不了解其调用顺序,很有可能遇到配置了环境变量,而没有其作用的问题 ...

  7. OpenHarmony设备的开发环境搭建与工程管理(Ubuntu系统环境)

    文章目录 开始前的废话 本篇文章是介绍在**Ubuntu环境**下,如何搭建一套完整的可视化开发环境.笔者经过测试Ubuntu 20.04系统环境下操作都可以实现. 开发环境的搭建 第一步: 修改Ub ...

  8. Linux入门开发: 从0开始搭建ubuntu系统环境(编写第一个C程序)

    前言 本篇文作为C语言.Linux入门环境搭建参考文章:真正的从0开始搭建Linux环境. 现在开发学习阶段,笔记本主要还是使用windows系统,为了方便学习Linux系统,重装系统或者安装双系统都 ...

  9. go给Linux安装mysql_在Linux上安装Go语言开发包

    前面我们介绍了在 Windows 系统上来搭建Go语言开发包,本节将为大家讲解在 Linux 平台安装Go语言开发包,大家可以在Go语言官网找到对应的安装包(https://golang.google ...

最新文章

  1. 有了这几个神器,瞬间逼格就上去了
  2. jquery $.post 超时_jQuery介绍
  3. CMake 指定安装目录
  4. 2019CCF自主可控计算机大会召开 中科院院士吁自力更生
  5. STM32开发 -- STM32初识
  6. 巨控 自建服务器,GRM云服务器的Web数据接口.PDF
  7. k6前级效果器怎么用_【易开EK-K6 DSP 专业 数字前级效果器 前置】价格_厂家_图片 -Hc360慧聪网...
  8. 【VS开发】ClientToScreen 和ScreenToClient 用法
  9. 我复盘了自己的工作,总结了这个跨境支付产品经理的成长经验给你
  10. 微信公众号迁移流程 《openid转换》
  11. 最新的鄞比 服务器mp4,阳光之下播出,彭冠英好适合傅慎行,和李承鄞比肩的人出来了...
  12. 网络维护汇总经典问题集
  13. 给定n位正整数a,去掉其中任意k个数字后,剩下的数字按原次序排列组成⼀个新的正整数,求组成的新数最小的删数方案(O((n-k)logk)优化)
  14. Python+Selenium自动化测试之页码,前一页、后一页、翻页
  15. 计算机绘制表格教案,电脑制作表格教案设计
  16. 图书管理系统(数据库版)
  17. 免费css布局和模板集合
  18. ie浏览器下载文件中文名称乱码
  19. Qt学习day03 Qt设计师(designer) Qt创造器(qtcreator)
  20. AutoJs学习-自动筛选探探对象

热门文章

  1. 英语口语266之每日十句口语
  2. 使用 Oracle Enterprise Manager Cloud Control 12c 安装和管理 Oracle Data Guard
  3. vue element-ui 优化打包 bundle js 大小
  4. Microsoft Excel 中 ROMAN 函数介绍
  5. 猿来小课Java视频教程讲师浅谈JAVA体系结构
  6. vue中input禁止输入中文_input禁止键盘及中文输入,但可以点击
  7. laravel 开发的双语网站_为什么开发人员讨厌PHP
  8. 在vue中使用element-ui 里面的按钮点击后显示加载中,防止重复提交
  9. 烤仔观察 | SEC 重拳出击,Brad Garlinghouse 能否成为拯救 Ripple 的关键先生?
  10. Revit二次开发—参数的读取与写入