如何把若干个函数单独放在一个文件里
以前的写法,就随便放在某个文件里,命名XX.C 然后在主文件里include<xx.c> 但是被告知 这是不规范用法 本帖最后由 hrpzcf 于 2022-5-19 15:39 编辑函数单独放.c文件,新建一个.h文件,定义所有函数原型,主xx.c文件内include .h文件,编译的时候指定所有.c文件,比如 gcc xx.c a.c b.c d.c -o main hrpzcf 发表于 2022-5-19 15:37
函数单独放.c文件,新建一个.h文件,定义所有函数原型,主xx.c文件内include .h文件,编译的时候指定所有.c ...
带点h的在编译时 不用到对应的lib吗 我用你的办法并没有生成中间文件
直接就是一个EXE 本帖最后由 hrpzcf 于 2022-5-19 17:08 编辑
wp231957 发表于 2022-5-19 15:52
带点h的在编译时 不用到对应的lib吗 我用你的办法并没有生成中间文件
直接就是一个EXE
要使用静态库lib的话,要改变编译方式。
1. 先把单独函数的 a.c b.c ... 文件生成编译成静态库 x.lib,百度;
2. 新建 .h 写上述.c文件的函数原型;
3. 主文件 xxx.c 中 include 有函数原型的 .h,把主文件和 x.lib 一起编译成完整的可执行文件,百度。
hrpzcf 发表于 2022-5-19 17:03
要使用静态库lib的话,要改变编译方式。
1. 先把单独函数的 a.c b.c ... 文件生成编译成静态库 x.lib ...
我不是这个意思,换个问法,我们最常用的printf的实现部分在哪里 wp231957 发表于 2022-5-19 17:58
我不是这个意思,换个问法,我们最常用的printf的实现部分在哪里
/lib/libc.so.6 $ nm libc.so.6 | grep "\<printf\>"
0000000000074c04 T printf
$ nm lib/libc.so.6 | grep "\<printf\>"
0000000000074c04 T printf
$
0000000000074c04 <_IO_printf>:
/* Write formatted output to stdout from the format string FORMAT.*/
/* VARARGS1 */
int
__printf (const char *format, ...)
{
74c04: 55 pushq%rbp
74c05: 48 89 e5 movq %rsp,%rbp
74c08: 48 81 ec e0 00 00 00 subq $0xe0,%rsp
74c0f: 48 89 bd 28 ff ff ff movq %rdi,-0xd8(%rbp)
74c16: 48 89 b5 58 ff ff ff movq %rsi,-0xa8(%rbp)
74c1d: 48 89 95 60 ff ff ff movq %rdx,-0xa0(%rbp)
74c24: 48 89 8d 68 ff ff ff movq %rcx,-0x98(%rbp)
74c2b: 4c 89 85 70 ff ff ff movq %r8,-0x90(%rbp)
74c32: 4c 89 8d 78 ff ff ff movq %r9,-0x88(%rbp)
74c39: 84 c0 testb%al,%al
74c3b: 74 20 je 74c5d <_IO_printf+0x59>
74c3d: 0f 29 45 80 movaps %xmm0,-0x80(%rbp)
74c41: 0f 29 4d 90 movaps %xmm1,-0x70(%rbp)
74c45: 0f 29 55 a0 movaps %xmm2,-0x60(%rbp)
74c49: 0f 29 5d b0 movaps %xmm3,-0x50(%rbp)
74c4d: 0f 29 65 c0 movaps %xmm4,-0x40(%rbp)
74c51: 0f 29 6d d0 movaps %xmm5,-0x30(%rbp)
74c55: 0f 29 75 e0 movaps %xmm6,-0x20(%rbp)
74c59: 0f 29 7d f0 movaps %xmm7,-0x10(%rbp)
va_list arg;
int done;
va_start (arg, format);
74c5d: c7 85 30 ff ff ff 08 movl $0x8,-0xd0(%rbp)
74c64: 00 00 00
74c67: c7 85 34 ff ff ff 30 movl $0x30,-0xcc(%rbp)
74c6e: 00 00 00
74c71: 48 8d 45 10 leaq 0x10(%rbp),%rax
74c75: 48 89 85 38 ff ff ff movq %rax,-0xc8(%rbp)
74c7c: 48 8d 85 50 ff ff ff leaq -0xb0(%rbp),%rax
74c83: 48 89 85 40 ff ff ff movq %rax,-0xc0(%rbp)
done = __vfprintf_internal (stdout, format, arg, 0);
74c8a: 48 8b 05 97 62 1d 00 movq 0x1d6297(%rip),%rax # 24af28 <stdout@@GLIBC_2.2.5-0x1928>
74c91: 48 8b 00 movq (%rax),%rax
74c94: 48 8d 95 30 ff ff ff leaq -0xd0(%rbp),%rdx
74c9b: 48 8b b5 28 ff ff ff movq -0xd8(%rbp),%rsi
74ca2: b9 00 00 00 00 movl $0x0,%ecx
74ca7: 48 89 c7 movq %rax,%rdi
74caa: e8 f0 4c 01 00 callq8999f <__vfprintf_internal>
74caf: 89 85 4c ff ff ff movl %eax,-0xb4(%rbp)
va_end (arg);
return done;
74cb5: 8b 85 4c ff ff ff movl -0xb4(%rbp),%eax
}
74cbb: c9 leaveq
74cbc: c3 retq
人造人 发表于 2022-5-19 18:49
那为什么只是引用stdio.h就可以访问这个lib里面的函数?这又是啥机制? $ ls
list.clist.hmain.c
$ cat list.h
#ifndef _LIST_H_
#define _LIST_H_
#include <stddef.h>
#include <stdbool.h>
struct list_node_tag {
void *data; size_t size;
struct list_node_tag *next;
};
typedef struct {
struct list_node_tag *head;
size_t size;
} list_t;
list_t *list_init(void);
void list_deinit(list_t *list);
bool list_clean(list_t *list);
bool list_insert(list_t *list, size_t index, const void *data, size_t size);
bool list_delete(list_t *list, size_t index);
bool list_get(const list_t *list, size_t index, void *data, size_t size);
bool list_set(list_t *list, size_t index, const void *data, size_t size);
bool list_append(list_t *list, const void *data, size_t size);
size_t list_size(const list_t *list);
bool list_empty(const list_t *list);
#endif
$ cat list.c
#include "list.h"
#include <stdlib.h>
#include <memory.h>
list_t *list_init(void) {
list_t *list = malloc(sizeof(*list));
if(!list) return NULL;
list->head = NULL;
list->size = 0;
return list;
}
void list_deinit(list_t *list) {
if(!list) return;
list_clean(list);
free(list);
}
bool list_clean(list_t *list) {
if(!list) return false;
while(!list_empty(list)) list_delete(list, 0);
return true;
}
bool list_insert(list_t *list, size_t index, const void *data, size_t size) {
if(!list) return false;
if(list_size(list) < index) return false;
if(!data) return false;
struct list_node_tag **current = &list->head;
while(index--) current = &(*current)->next;
struct list_node_tag *node = malloc(sizeof(*node));
if(!node) return false;
node->data = malloc(size);
if(!node->data) {free(node); return false;}
memcpy(node->data, data, size);
node->size = size;
node->next = *current;
*current = node;
++list->size;
return true;
}
bool list_delete(list_t *list, size_t index) {
if(!list) return false;
if(list_size(list) <= index) return false;
struct list_node_tag **current = &list->head;
while(index--) current = &(*current)->next;
struct list_node_tag *temp = *current;
*current = temp->next;
free(temp->data); free(temp);
--list->size;
return true;
}
bool list_get(const list_t *list, size_t index, void *data, size_t size) {
if(!list) return false;
if(list_size(list) <= index) return false;
if(!data) return false;
struct list_node_tag *const *current = &list->head;
while(index--) current = &(*current)->next;
struct list_node_tag *temp = *current;
if(temp->size > size) return false;
memcpy(data, temp->data, temp->size);
return true;
}
bool list_set(list_t *list, size_t index, const void *data, size_t size) {
bool res = list_delete(list, index);
return res ? list_insert(list, index, data, size) : res;
}
bool list_append(list_t *list, const void *data, size_t size) {
if(!list) return false;
return list_insert(list, list_size(list), data, size);
}
size_t list_size(const list_t *list) {
if(!list) return 0;
return list->size;
}
bool list_empty(const list_t *list) {
if(!list) return true;
return list_size(list) == 0;
}
$ cat main.c
#include "list.h"
#include <stdio.h>
void output(const list_t *list, size_t index) {
if(index >= list_size(list)) return;
output(list, index + 1);
int temp; list_get(list, index, &temp, sizeof(temp));
printf("%d ", temp);
}
int main(void) {
list_t *list = list_init();
for(size_t i = 0; i < 5; ++i) {
int temp; scanf("%d", &temp);
list_append(list, &temp, sizeof(temp));
}
output(list, 0); puts("");
list_deinit(list);
return 0;
}
$ gcc-debug -o main main.c list.c
$ ./main
1 2 3 4 5
5 4 3 2 1
$ 人造人 发表于 2022-5-19 19:05
这个和我问的那个stdio的有关系吗?实在是没看懂啊 wp231957 发表于 2022-5-19 19:02
那为什么只是引用stdio.h就可以访问这个lib里面的函数?这又是啥机制?
stdio.h 里面就是有一个printf函数的声明,你自己声明一下printf函数,就不需要#include <stdio.h> 了
每一个c程序都会用到libc,你在编译代码的时候,即使你没有要求连接libc库,gcc也默认连接了这个库
$ cat main.c
//#include <stdio.h>
int printf(const char *format, ...);
int main(void) {
printf("hello world!\n");
return 0;
}
$ gcc-debug -o main main.c
$ ./main
hello world!
$ wp231957 发表于 2022-5-19 19:08
这个和我问的那个stdio的有关系吗?实在是没看懂啊
如何把若干个函数单独放在一个文件里
这个代码是我写的一个通用list
一个.c源文件到可执行文件其实是有好多步骤的
gcc一条命令就可以完成全部的任务,当然它也允许你在某一个位置停下来
$ ls
main.c
$ cat main.c
//#include <stdio.h>
int printf(const char *format, ...);
int main(void) {
printf("hello world!\n");
return 0;
}
$ cpp main.c >main.i # 预处理
$ ls
main.cmain.i
$ gcc -S -o main.s main.i # 编译
$ ls
main.cmain.imain.s
$ as -o main.o main.s # 汇编
$ ls
main.cmain.imain.omain.s
$ ld -o main main.o -dynamic-linker /lib/ld-linux-x86-64.so.2 /lib/Scrt1.o /lib/libc.so.6 # 连接
$ ls
mainmain.cmain.imain.omain.s
$ ./main
hello world!
$ $ cat main.i
# 0 "main.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "main.c"
int printf(const char *format, ...);
int main(void) {
printf("hello world!\n");
return 0;
}
$ cat main.s
.file "main.c"
.text
.section .rodata
.LC0:
.string "hello world!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rax
movq %rax, %rdi
call puts@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 12.1.0"
.section .note.GNU-stack,"",@progbits
$ objdump -S -M suffix main.o
main.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 pushq%rbp
1: 48 89 e5 movq %rsp,%rbp
4: 48 8d 05 00 00 00 00 leaq 0x0(%rip),%rax # b <main+0xb>
b: 48 89 c7 movq %rax,%rdi
e: e8 00 00 00 00 callq13 <main+0x13>
13: b8 00 00 00 00 movl $0x0,%eax
18: 5d popq %rbp
19: c3 retq
$ objdump -S -M suffix main
main: file format elf64-x86-64
Disassembly of section .plt:
0000000000401000 <puts@plt-0x10>:
401000: ff 35 02 30 00 00 pushq0x3002(%rip) # 404008 <_GLOBAL_OFFSET_TABLE_+0x8>
401006: ff 25 04 30 00 00 jmpq *0x3004(%rip) # 404010 <_GLOBAL_OFFSET_TABLE_+0x10>
40100c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000401010 <puts@plt>:
401010: ff 25 02 30 00 00 jmpq *0x3002(%rip) # 404018 <puts@GLIBC_2.2.5>
401016: 68 00 00 00 00 pushq$0x0
40101b: e9 e0 ff ff ff jmpq 401000 <__abi_tag+0xcc0>
Disassembly of section .text:
0000000000401020 <main>:
401020: 55 pushq%rbp
401021: 48 89 e5 movq %rsp,%rbp
401024: 48 8d 05 d5 0f 00 00 leaq 0xfd5(%rip),%rax # 402000 <_start+0xfc0>
40102b: 48 89 c7 movq %rax,%rdi
40102e: e8 dd ff ff ff callq401010 <puts@plt>
401033: b8 00 00 00 00 movl $0x0,%eax
401038: 5d popq %rbp
401039: c3 retq
40103a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
0000000000401040 <_start>:
401040: f3 0f 1e fa endbr64
401044: 31 ed xorl %ebp,%ebp
401046: 49 89 d1 movq %rdx,%r9
401049: 5e popq %rsi
40104a: 48 89 e2 movq %rsp,%rdx
40104d: 48 83 e4 f0 andq $0xfffffffffffffff0,%rsp
401051: 50 pushq%rax
401052: 54 pushq%rsp
401053: 45 31 c0 xorl %r8d,%r8d
401056: 31 c9 xorl %ecx,%ecx
401058: 48 c7 c7 20 10 40 00 movq $0x401020,%rdi
40105f: ff 15 93 2f 00 00 callq*0x2f93(%rip) # 403ff8 <__libc_start_main@GLIBC_2.34>
401065: f4 hlt
$ 人造人 发表于 2022-5-19 19:57
原来,没有头文件真的能运行呀
int printf (const char *__restrict, ...);
double sqrt (double);
int main()
{
printf("a+b=%lf\n",sqrt(15));
return 0;
}
页:
[1]