【发布时间】: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
我又花了一个小时试图解决这个问题.. 通过尝试和错误,但徒劳无功。你能指出发生了什么吗?我该怎么办?
(任何其他建议也将不胜感激。)
【问题讨论】:
-
删除
-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。简而言之就是这样。
标签: linux command-line shell gcc c