如何使用 `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
是如何工作的,然后回来理解代码。我们的目标是重复这个过程,直到我能舒服地阅读他们更大的程序的源代码,比如sent
、dmenu
、dwm
。
在代码中,标题#include "util.h"
建议我将上面链接中的另一个文件util.h
与echo.c
放在一起。我还包括arg.h
和compat.h
因为util.h
的标题说
#include <sys/types.h>
#include <regex.h>
#include <stddef.h>
#include <stdio.h>
#include "arg.h"
#include "compat.h"
我进一步检查了arg.h
和compat.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 <stdio.h>
。如果您习惯于检查您使用的每个功能的手册页,例如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 程序?的主要内容,如果未能解决你的问题,请参考以下文章