如何使用 `gcc` 编译和运行 C 程序?

Posted

技术标签:

【中文标题】如何使用 `gcc` 编译和运行 C 程序?【英文标题】:How to compile and run a C program with `gcc`? 【发布时间】:2020-06-28 22:49:12 【问题描述】:

这里是一个完整的新手。我正在学习阅读suckless.org 上的代码。它们是用 C 编写的,而且最简短,所以我认为这是一个好的开始。

问题是我知道的太少,无法开始。逛了一圈,发现suckless社区都有自己的coreutils,也很短。 echo.c 这个page 是最短的之一。我在这里包括它的标题:

/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <string.h>
#include "util.h"

我想编译它,看看这个版本的echo 是如何工作的,然后回来理解代码。我们的目标是重复这个过程,直到我能舒服地阅读他们更大的程序的源代码,比如sentdmenudwm

在代码中,标题#include "util.h" 建议我将上面链接中的另一个文件util.hecho.c 放在一起。我还包括arg.hcompat.h 因为util.h 的标题说

#include <sys/types.h>

#include <regex.h>
#include <stddef.h>
#include <stdio.h>

#include "arg.h"
#include "compat.h"

我进一步检查了arg.hcompat.h。它们都不包含自定义的头文件,所以我想我很高兴。现在文件夹树看起来像

$ tree
.
├── arg.h
├── compat.h
├── echo.c
└── util.h

然后我运行$ gcc echo.c -o echo.o。但是,我遇到了错误

/usr/bin/ld: /tmp/cc2VjXNO.o: in function `main':
echo.c:(.text+0x20): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x27): undefined reference to `argv0'
/usr/bin/ld: echo.c:(.text+0x8d): undefined reference to `putword'
/usr/bin/ld: echo.c:(.text+0xc8): undefined reference to `fshut'
collect2: error: ld returned 1 exit status

显然,这些未定义的参数在那些头文件中。在网上搜索了一下,我进一步尝试了

$ gcc -c . echo.c -o echo.o
gcc: warning: .: linker input file unused because linking not done

它会发出警告,但无论如何都会发送echo.o。我chmod它可执行,并由$ ./echo.o运行它,但我的shell抱怨

zsh: exec format error: ./echo.o

我又花了一个小时试图解决这个问题.. 通过尝试和错误,但徒劳无功。你能指出发生了什么吗?我该怎么办?

(任何其他建议也将不胜感激。)

【问题讨论】:

en.wikipedia.org/wiki/Compiler 这能回答你的问题吗? What is an undefined reference/unresolved external symbol error and how do I fix it? 删除-c .I got an error 符号未定义。因此,将它们包含在您的编译中。您通常不能从项目中获取一个文件,然后将其与所有其他文件分开编译,而不包括所有依赖项。 头文件包括常量和函数声明,无论您包含在需要它们的源文件中的什么,都需要这些声明。例如,如果您在代码中包含puts ("my dog has fleas.");,那么对于puts() 的标准I/O 函数声明,您需要#include &lt;stdio.h&gt;。如果您习惯于检查您使用的每个功能的手册页,例如man 3 puts,它会在"SYNOPSIS" 下告诉您确切需要哪个标头。没有魔法。 使用gcc 编译时,始终通过包含-Wall -Wextra -pedantic 来启用警告,并且在编译没有警告之前不要接受代码(还建议包含-Wshadow 以捕获任何阴影变量)。您的基本编译(不包括警告选项)是gcc -o nameyouwant yoursource.c [other.c ...],将yoursource.c 编译成名为nameyouwant 的可执行文件。 (您可以根据需要指定任意数量的other.c 文件)将-O0 添加到-O3 以实现几乎完整的优化。添加-std=c11 以指定C11 standard。简而言之就是这样。 【参考方案1】:

您尝试使用您没有的库编译程序。您使用的标头需要动态或静态库(Linux 上的 .a 或 .o)。这就是你得到linker input file unused because linking not done的原因。

zsh: exec format error: ./echo.o 如果您使用带有 -o 参数的 .o 扩展名,则您正在创建或链接一个 .o 目标文件(静态库)。使用gcc -c . echo.c -o echo.o,您正在创建一个无法执行的静态库(称为对象)。

顺便说一句,我暂时远离这种代码,它对学习者来说非常不友好。

【讨论】:

感谢您的回答!我认为了解 makefile 的内容是不可避免的。也感谢您的建议。我正在考虑通过潜入深海学习游泳,希望这能让我学得更快。如果我周围有经验丰富的朋友,效果最好,但对于这种情况.. 我最好听从你的建议。

以上是关于如何使用 `gcc` 编译和运行 C 程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在cmd中编译命名运行c程序

Linux下如何编译,运行C程序?需要安装编译器吗

cmd调用gcc编译运行c语言后,c语言会再产生一个窗口显示结果,如何将这些内容显示在cmd命令窗口中?

如何在Unix 下运行c语言?

如何使 gcc 警告缩小函数参数

程序员三大浪漫之编译器:如何编译和运行c++程序