[英]Undefined function reference in C
I've several files with main functions in C, for example, I've files called show.c , delete.c add.c (...). 我还有一个文件,名为interpreter.c ,它可能会调用其中一个文件,例如delete.c 。 这些文件中的大多数都实现了一个主要的 function,例如delete.c :
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char *argv[])
{
int fd, rm;
char *caminho = argv[1]; // argumento inserido no terminal
char caminhod[30]="../TPSOFinal/";
strcat(caminhod,argv[1]);
fd = open(caminhod, O_RDONLY);
rm=unlink(caminhod);
// Verifica se o caminho inserido no input existe
if(rm == 0){
write(1,"Ficheiro eliminado!!!\n", 22);
return 0;
}
else{
write(1,"Erro ao eliminar ficheiro !!!\n", 29);
perror("Erro");
}
return 0;
close(fd);
}
口译员:
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <readline/readline.h>
#include <readline/history.h>
#define LER_BUFFER 1024
#define TBUFF 64
#define DELIM "\t\r\n\a"
int mostra(char **args);
int conta(char **args);
int acrescenta(char **args);
int apaga(char **args);
int informa(char **args);
int lista(char **args);
int manual(char **args);
int termina(char **args);
char *comando[] =
{
"mostra <caminho>",
"conta <caminho>",
"acrescenta <caminho> <caminho destino>",
"apaga <caminho>",
"informa <caminho>",
"lista <caminho>",
"manual",
"termina",
" ",
};
int (*fcomandos[]) (char**) =
{
&mostra,
&conta,
&acrescenta,
&apaga,
&informa,
&lista,
&manual,
&termina
};
int ncomandos()
{
return sizeof(comando)/sizeof(char*);
}
void processa(char *linha, char **argv)
{
while(*linha != '\0')
{
while(*linha == ' ' || *linha == '\t' || *linha == '\n')
{
*linha++ = '\0'; //troca caracteres especiais
}
*argv++ = linha; //guarda posição
while (*linha != '\0' && *linha != ' ' && *linha != '\t' && *linha != '\n')
{
linha++;
}
}
*argv = NULL;
}
char *lerlinha (void)
{
char *linha = NULL;
ssize_t tam = 0;
getline (&linha, &tam, stdin);
return linha;
}
char **separa (char *linha)
{
int tam = TBUFF, pos = 0;
char **palavras = malloc (tam *sizeof(char*));
char *palavra;
if (!palavras)
{
perror("Erro");
exit(EXIT_FAILURE);
}
palavra = strtok (linha, DELIM);
while (palavra != NULL)
{
palavras [pos] = palavra;
pos ++;
if (pos >= tam)
{
perror ("Erro");
}
}
palavra = strtok(NULL, DELIM);
palavras [pos] = NULL;
return palavras;
}
int launch (char **args)
{
pid_t pid, wpid;
int estado;
pid = fork();
if (pid == 0)
{
if(execvp(args[0],args)==-1){ perror ("Erro!"); }
exit (EXIT_FAILURE);
}
if (pid <0)
{
perror ("Erro!");
}
else
{
do{wpid = waitpid(pid, &estado, WUNTRACED);}
while (!WIFEXITED(estado)&& !WIFSIGNALED(estado));
}
return 1;
}
//Testa se os comandos existem
int mostra (char **args)
{
if (args[1] == NULL)
{
perror("sem argumentos ");
}
else if (chdir (args[1]) != 0)
{
perror ("Erro!");
}
return 1;
}
int conta ( char ** args)
{
if (args[1] == NULL)
{
perror("Sem argumentos ");
}
else if (chdir (args[1])!= 0)
{
perror ("Erro!");
}
return 1;
}
// Manual dos comandos
int manual (char **args)
{
int i;
printf("\n\nMiguel Oliveira\n");
printf("10260 - LESI\n");
printf("Sistemas Operativos e Sistemas Distribuidos\n");
printf("\nLista de Comandos\n");
for (i=0; i<ncomandos(); i++)
{
printf("%s\n", comando[i]);
}
return 1;
}
int termina (char **args)
{
return 0;
}
//Executa os comandos
int executar (char **args)
{
int i;
if (args[0] == NULL)
{
return 1;
}
for (i=0; i<ncomandos(); i++)
{
if (strcmp(args[0], comando[i])==0)
{
return (*fcomandos[i])(args);
}
}
return launch(args);
}
//Interpretador
void interpretador (void)
{
char *linha;
char **args;
int estado;
do
{
printf("%% ");
linha = lerlinha();
args = separa(linha);
estado = executar(args);
free(linha);
free(args);
} while (estado);
}
int main (void)
{
interpretador();
return EXIT_SUCCESS;
}
我试图研究类似的问题,我发现了一些可能的解决方案,但无法解决我的问题,如底部GCC 编译错误所示
您不会“调用源文件”; 源文件定义函数和变量,并且在编译时,如果不同文件中定义的文件具有声明(通常在 header 文件中)或指针(通过动态链接方法,如 POSIX dlsym()),则它们可以相互使用。
考虑这个最小的例子。 首先, example.c :
#include <stdlib.h>
#include <stdio.h>
/* We expect someone else to define these */
extern int one(void);
int main(void)
{
printf("one() returned %d.\n", one());
return EXIT_SUCCESS;
}
和helper.c :
int one(void)
{
return 2; /* TODO: It's not one! */
}
您将每个源文件编译为 object 文件:
gcc -Wall -O2 -c example.c
gcc -Wall -O2 -c helper.c
然后将它们链接到一个可执行程序:
gcc -Wall -O2 example.o helper.o -o program
您可以使用它运行
./program
通常,每个提供可在该文件之外使用的函数或变量的 C 源文件都会在 header 文件中声明它们。 这是一个更好的例子。
度数.h
#ifndef DEGREES_H
#define DEGREES_H
double radians_to_degrees(double);
double degrees_to_radians(double);
#endif /* DEGREES_H */
#ifndef
、 #define
和#endif
用作警卫,因此如果您多次#include
文件,则函数只会被声明一次。 (如果看到多个声明,编译器会报错。另外,我们不需要在这里使用extern
。)
那么上面的实现就是度数。c ,
#ifndef PI
#define PI 3.14159265358979323846
#endif
double degrees_to_radians(double degrees)
{
return degrees * PI / 180.0;
}
double radians_to_degrees(double radians)
{
return radians * 180.0 / PI;
}
在同一个项目中的程序myprog.c中,您将使用上述代码:
#include <stdlib.h>
#include <stdio.h>
#include "degrees.h"
int main(void)
{
printf("45 degrees is %.6f radians.\n", degrees_to_radians(45.0));
printf("2 radians is %.3f degrees.\n", radians_to_degrees(2.0));
return EXIT_SUCCESS;
}
再次将两个源文件编译为 object 文件,
gcc -Wall -O2 -c degrees.c
gcc -Wall -O2 -c myprog.c
然后链接到一个程序,比如myprog ,
gcc -Wall -O2 degrees.o myprog.o -o myprog
然后您可以运行:
./myprog
也可以将 degree.h 中声明的函数和变量编译并链接到static ( libdegrees.a
) 或动态 ( libdegrees.so
) 库,并将 header 文件安装到标准位置,以便您的程序可以而是使用#include <degrees.h>
和通过-ldegrees
链接到库的程序,但在您能够很好地处理多个文件之前,最好不要这样做。
在那之前,您可能会发现以下Makefile很有用
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS :=
PROGS := myprog
all: clean $(PROGS)
clean:
rm -f *.o $(PROGS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
myprog: degrees.o myprog.o
$(CC) $(CFLAGS) $^ -o $@
您可以在PROGS
行中添加多个程序,用空格分隔,并复制myprog:
为每个行,列出程序所需的 object 文件。
有了这个,编译程序所需要做的就是输入make
。
这个论坛吃标签,而 Makefiles 需要缩进才能使用它们。 因此,如果您只是将其复制粘贴到文件中,它将无法正常工作。 但是,您可以通过运行来修复它
sed -e 's|^ *|\t|' -i Makefile
它使用文件 Makefile 中的制表符删除每行上的所有初始空格。
如果您使用单独的库,通常是libm
( #include <math.h>
),您只需将-lm
(dash ell em) 添加到LDFLAGS
行。 如果您最终使用动态链接,那就是-ldl
。
如果您要使用 Gtk+ 编写图形程序,您将 append ` pkg-config --cflags gtk+-3.0
`(包括反引号 `)到CFLAGS
行,以及 ` pkg-config --libs gtk+-3.0
` LDFLAGS
行和#include <gtk/gtk.h>
到您的程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.