鱼C论坛

 找回密码
 立即注册
查看: 1487|回复: 15

[已解决]如何把若干个函数单独放在一个文件里

[复制链接]
发表于 2022-5-19 15:18:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
以前的写法,就随便放在某个文件里,命名XX.C   然后在主文件里  include  <xx.c>    但是被告知 这是不规范用法
最佳答案
2022-5-19 15:37:42
本帖最后由 hrpzcf 于 2022-5-19 15:39 编辑

函数单独放.c文件,新建一个.h文件,定义所有函数原型,主xx.c文件内include .h文件,编译的时候指定所有.c文件,比如 gcc xx.c a.c b.c d.c -o main
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-5-19 15:37:42 | 显示全部楼层    本楼为最佳答案   
本帖最后由 hrpzcf 于 2022-5-19 15:39 编辑

函数单独放.c文件,新建一个.h文件,定义所有函数原型,主xx.c文件内include .h文件,编译的时候指定所有.c文件,比如 gcc xx.c a.c b.c d.c -o main
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-19 15:52:13 | 显示全部楼层
hrpzcf 发表于 2022-5-19 15:37
函数单独放.c文件,新建一个.h文件,定义所有函数原型,主xx.c文件内include .h文件,编译的时候指定所有.c ...

带点h的  在编译时 不用到对应的lib吗   我用你的办法并没有生成中间文件
直接就是一个EXE
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 17:03:34 | 显示全部楼层
本帖最后由 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 一起编译成完整的可执行文件,百度。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-19 17:58:32 From FishC Mobile | 显示全部楼层
hrpzcf 发表于 2022-5-19 17:03
要使用静态库lib的话,要改变编译方式。
1. 先把单独函数的 a.c b.c ... 文件生成编译成静态库 x.lib ...

我不是这个意思,换个问法,我们最常用的printf的实现部分在哪里
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 18:37:41 | 显示全部楼层
wp231957 发表于 2022-5-19 17:58
我不是这个意思,换个问法,我们最常用的printf的实现部分在哪里
  1. /lib/libc.so.6
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 18:49:36 | 显示全部楼层
  1. $ nm libc.so.6 | grep "\<printf\>"
  2. 0000000000074c04 T printf
复制代码


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:00:21 | 显示全部楼层
  1. $ nm lib/libc.so.6 | grep "\<printf\>"
  2. 0000000000074c04 T printf
  3. $
复制代码

  1. 0000000000074c04 <_IO_printf>:

  2. /* Write formatted output to stdout from the format string FORMAT.  */
  3. /* VARARGS1 */
  4. int
  5. __printf (const char *format, ...)
  6. {
  7.    74c04:        55                           pushq  %rbp
  8.    74c05:        48 89 e5                     movq   %rsp,%rbp
  9.    74c08:        48 81 ec e0 00 00 00         subq   $0xe0,%rsp
  10.    74c0f:        48 89 bd 28 ff ff ff         movq   %rdi,-0xd8(%rbp)
  11.    74c16:        48 89 b5 58 ff ff ff         movq   %rsi,-0xa8(%rbp)
  12.    74c1d:        48 89 95 60 ff ff ff         movq   %rdx,-0xa0(%rbp)
  13.    74c24:        48 89 8d 68 ff ff ff         movq   %rcx,-0x98(%rbp)
  14.    74c2b:        4c 89 85 70 ff ff ff         movq   %r8,-0x90(%rbp)
  15.    74c32:        4c 89 8d 78 ff ff ff         movq   %r9,-0x88(%rbp)
  16.    74c39:        84 c0                        testb  %al,%al
  17.    74c3b:        74 20                        je     74c5d <_IO_printf+0x59>
  18.    74c3d:        0f 29 45 80                  movaps %xmm0,-0x80(%rbp)
  19.    74c41:        0f 29 4d 90                  movaps %xmm1,-0x70(%rbp)
  20.    74c45:        0f 29 55 a0                  movaps %xmm2,-0x60(%rbp)
  21.    74c49:        0f 29 5d b0                  movaps %xmm3,-0x50(%rbp)
  22.    74c4d:        0f 29 65 c0                  movaps %xmm4,-0x40(%rbp)
  23.    74c51:        0f 29 6d d0                  movaps %xmm5,-0x30(%rbp)
  24.    74c55:        0f 29 75 e0                  movaps %xmm6,-0x20(%rbp)
  25.    74c59:        0f 29 7d f0                  movaps %xmm7,-0x10(%rbp)
  26.   va_list arg;
  27.   int done;

  28.   va_start (arg, format);
  29.    74c5d:        c7 85 30 ff ff ff 08         movl   $0x8,-0xd0(%rbp)
  30.    74c64:        00 00 00
  31.    74c67:        c7 85 34 ff ff ff 30         movl   $0x30,-0xcc(%rbp)
  32.    74c6e:        00 00 00
  33.    74c71:        48 8d 45 10                  leaq   0x10(%rbp),%rax
  34.    74c75:        48 89 85 38 ff ff ff         movq   %rax,-0xc8(%rbp)
  35.    74c7c:        48 8d 85 50 ff ff ff         leaq   -0xb0(%rbp),%rax
  36.    74c83:        48 89 85 40 ff ff ff         movq   %rax,-0xc0(%rbp)
  37.   done = __vfprintf_internal (stdout, format, arg, 0);
  38.    74c8a:        48 8b 05 97 62 1d 00         movq   0x1d6297(%rip),%rax        # 24af28 <stdout@@GLIBC_2.2.5-0x1928>
  39.    74c91:        48 8b 00                     movq   (%rax),%rax
  40.    74c94:        48 8d 95 30 ff ff ff         leaq   -0xd0(%rbp),%rdx
  41.    74c9b:        48 8b b5 28 ff ff ff         movq   -0xd8(%rbp),%rsi
  42.    74ca2:        b9 00 00 00 00               movl   $0x0,%ecx
  43.    74ca7:        48 89 c7                     movq   %rax,%rdi
  44.    74caa:        e8 f0 4c 01 00               callq  8999f <__vfprintf_internal>
  45.    74caf:        89 85 4c ff ff ff            movl   %eax,-0xb4(%rbp)
  46.   va_end (arg);

  47.   return done;
  48.    74cb5:        8b 85 4c ff ff ff            movl   -0xb4(%rbp),%eax
  49. }
  50.    74cbb:        c9                           leaveq
  51.    74cbc:        c3                           retq   
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-19 19:02:29 From FishC Mobile | 显示全部楼层
人造人 发表于 2022-5-19 18:49

那为什么只是引用stdio.h就可以访问这个lib里面的函数?这又是啥机制?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:05:11 | 显示全部楼层
  1. $ ls
  2. list.c  list.h  main.c
  3. $ cat list.h
  4. #ifndef _LIST_H_
  5. #define _LIST_H_

  6. #include <stddef.h>
  7. #include <stdbool.h>

  8. struct list_node_tag {
  9.     void *data; size_t size;
  10.     struct list_node_tag *next;
  11. };

  12. typedef struct {
  13.     struct list_node_tag *head;
  14.     size_t size;
  15. } list_t;

  16. list_t *list_init(void);
  17. void list_deinit(list_t *list);
  18. bool list_clean(list_t *list);
  19. bool list_insert(list_t *list, size_t index, const void *data, size_t size);
  20. bool list_delete(list_t *list, size_t index);
  21. bool list_get(const list_t *list, size_t index, void *data, size_t size);
  22. bool list_set(list_t *list, size_t index, const void *data, size_t size);
  23. bool list_append(list_t *list, const void *data, size_t size);
  24. size_t list_size(const list_t *list);
  25. bool list_empty(const list_t *list);

  26. #endif
  27. $ cat list.c
  28. #include "list.h"
  29. #include <stdlib.h>
  30. #include <memory.h>

  31. list_t *list_init(void) {
  32.     list_t *list = malloc(sizeof(*list));
  33.     if(!list) return NULL;
  34.     list->head = NULL;
  35.     list->size = 0;
  36.     return list;
  37. }

  38. void list_deinit(list_t *list) {
  39.     if(!list) return;
  40.     list_clean(list);
  41.     free(list);
  42. }

  43. bool list_clean(list_t *list) {
  44.     if(!list) return false;
  45.     while(!list_empty(list)) list_delete(list, 0);
  46.     return true;
  47. }

  48. bool list_insert(list_t *list, size_t index, const void *data, size_t size) {
  49.     if(!list) return false;
  50.     if(list_size(list) < index) return false;
  51.     if(!data) return false;
  52.     struct list_node_tag **current = &list->head;
  53.     while(index--) current = &(*current)->next;
  54.     struct list_node_tag *node = malloc(sizeof(*node));
  55.     if(!node) return false;
  56.     node->data = malloc(size);
  57.     if(!node->data) {free(node); return false;}
  58.     memcpy(node->data, data, size);
  59.     node->size = size;
  60.     node->next = *current;
  61.     *current = node;
  62.     ++list->size;
  63.     return true;
  64. }

  65. bool list_delete(list_t *list, size_t index) {
  66.     if(!list) return false;
  67.     if(list_size(list) <= index) return false;
  68.     struct list_node_tag **current = &list->head;
  69.     while(index--) current = &(*current)->next;
  70.     struct list_node_tag *temp = *current;
  71.     *current = temp->next;
  72.     free(temp->data); free(temp);
  73.     --list->size;
  74.     return true;
  75. }

  76. bool list_get(const list_t *list, size_t index, void *data, size_t size) {
  77.     if(!list) return false;
  78.     if(list_size(list) <= index) return false;
  79.     if(!data) return false;
  80.     struct list_node_tag *const *current = &list->head;
  81.     while(index--) current = &(*current)->next;
  82.     struct list_node_tag *temp = *current;
  83.     if(temp->size > size) return false;
  84.     memcpy(data, temp->data, temp->size);
  85.     return true;
  86. }

  87. bool list_set(list_t *list, size_t index, const void *data, size_t size) {
  88.     bool res = list_delete(list, index);
  89.     return res ? list_insert(list, index, data, size) : res;
  90. }

  91. bool list_append(list_t *list, const void *data, size_t size) {
  92.     if(!list) return false;
  93.     return list_insert(list, list_size(list), data, size);
  94. }

  95. size_t list_size(const list_t *list) {
  96.     if(!list) return 0;
  97.     return list->size;
  98. }

  99. bool list_empty(const list_t *list) {
  100.     if(!list) return true;
  101.     return list_size(list) == 0;
  102. }
  103. $ cat main.c
  104. #include "list.h"
  105. #include <stdio.h>

  106. void output(const list_t *list, size_t index) {
  107.     if(index >= list_size(list)) return;
  108.     output(list, index + 1);
  109.     int temp; list_get(list, index, &temp, sizeof(temp));
  110.     printf("%d ", temp);
  111. }

  112. int main(void) {
  113.     list_t *list = list_init();
  114.     for(size_t i = 0; i < 5; ++i) {
  115.         int temp; scanf("%d", &temp);
  116.         list_append(list, &temp, sizeof(temp));
  117.     }
  118.     output(list, 0); puts("");
  119.     list_deinit(list);
  120.     return 0;
  121. }
  122. $ gcc-debug -o main main.c list.c
  123. $ ./main
  124. 1 2 3 4 5
  125. 5 4 3 2 1
  126. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-19 19:08:50 From FishC Mobile | 显示全部楼层
人造人 发表于 2022-5-19 19:05

这个和我问的那个stdio的有关系吗?实在是没看懂啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:19:21 | 显示全部楼层
wp231957 发表于 2022-5-19 19:02
那为什么只是引用stdio.h就可以访问这个lib里面的函数?这又是啥机制?

stdio.h 里面就是有一个printf函数的声明,你自己声明一下printf函数,就不需要#include <stdio.h> 了

每一个c程序都会用到libc,你在编译代码的时候,即使你没有要求连接libc库,gcc也默认连接了这个库


  1. $ cat main.c
  2. //#include <stdio.h>

  3. int printf(const char *format, ...);

  4. int main(void) {
  5.     printf("hello world!\n");
  6.     return 0;
  7. }
  8. $ gcc-debug -o main main.c
  9. $ ./main
  10. hello world!
  11. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:20:33 | 显示全部楼层
wp231957 发表于 2022-5-19 19:08
这个和我问的那个stdio的有关系吗?实在是没看懂啊
如何把若干个函数单独放在一个文件里


这个代码是我写的一个通用list
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:55:38 | 显示全部楼层
一个.c源文件到可执行文件其实是有好多步骤的
gcc一条命令就可以完成全部的任务,当然它也允许你在某一个位置停下来

  1. $ ls
  2. main.c
  3. $ cat main.c
  4. //#include <stdio.h>

  5. int printf(const char *format, ...);

  6. int main(void) {
  7.     printf("hello world!\n");
  8.     return 0;
  9. }
  10. $ cpp main.c >main.i          # 预处理
  11. $ ls
  12. main.c  main.i
  13. $ gcc -S -o main.s main.i     # 编译
  14. $ ls
  15. main.c  main.i  main.s
  16. $ as -o main.o main.s         # 汇编
  17. $ ls
  18. main.c  main.i  main.o  main.s
  19. $ ld -o main main.o -dynamic-linker /lib/ld-linux-x86-64.so.2 /lib/Scrt1.o /lib/libc.so.6    # 连接
  20. $ ls
  21. main  main.c  main.i  main.o  main.s
  22. $ ./main
  23. hello world!
  24. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-19 19:57:32 | 显示全部楼层
  1. $ cat main.i
  2. # 0 "main.c"
  3. # 0 "<built-in>"
  4. # 0 "<command-line>"
  5. # 1 "/usr/include/stdc-predef.h" 1 3 4
  6. # 0 "<command-line>" 2
  7. # 1 "main.c"


  8. int printf(const char *format, ...);

  9. int main(void) {
  10.     printf("hello world!\n");
  11.     return 0;
  12. }
  13. $ cat main.s
  14.         .file        "main.c"
  15.         .text
  16.         .section        .rodata
  17. .LC0:
  18.         .string        "hello world!"
  19.         .text
  20.         .globl        main
  21.         .type        main, @function
  22. main:
  23. .LFB0:
  24.         .cfi_startproc
  25.         pushq        %rbp
  26.         .cfi_def_cfa_offset 16
  27.         .cfi_offset 6, -16
  28.         movq        %rsp, %rbp
  29.         .cfi_def_cfa_register 6
  30.         leaq        .LC0(%rip), %rax
  31.         movq        %rax, %rdi
  32.         call        puts@PLT
  33.         movl        $0, %eax
  34.         popq        %rbp
  35.         .cfi_def_cfa 7, 8
  36.         ret
  37.         .cfi_endproc
  38. .LFE0:
  39.         .size        main, .-main
  40.         .ident        "GCC: (GNU) 12.1.0"
  41.         .section        .note.GNU-stack,"",@progbits
  42. $ objdump -S -M suffix main.o

  43. main.o:     file format elf64-x86-64


  44. Disassembly of section .text:

  45. 0000000000000000 <main>:
  46.    0:        55                           pushq  %rbp
  47.    1:        48 89 e5                     movq   %rsp,%rbp
  48.    4:        48 8d 05 00 00 00 00         leaq   0x0(%rip),%rax        # b <main+0xb>
  49.    b:        48 89 c7                     movq   %rax,%rdi
  50.    e:        e8 00 00 00 00               callq  13 <main+0x13>
  51.   13:        b8 00 00 00 00               movl   $0x0,%eax
  52.   18:        5d                           popq   %rbp
  53.   19:        c3                           retq
  54. $ objdump -S -M suffix main

  55. main:     file format elf64-x86-64


  56. Disassembly of section .plt:

  57. 0000000000401000 <puts@plt-0x10>:
  58.   401000:        ff 35 02 30 00 00            pushq  0x3002(%rip)        # 404008 <_GLOBAL_OFFSET_TABLE_+0x8>
  59.   401006:        ff 25 04 30 00 00            jmpq   *0x3004(%rip)        # 404010 <_GLOBAL_OFFSET_TABLE_+0x10>
  60.   40100c:        0f 1f 40 00                  nopl   0x0(%rax)

  61. 0000000000401010 <puts@plt>:
  62.   401010:        ff 25 02 30 00 00            jmpq   *0x3002(%rip)        # 404018 <puts@GLIBC_2.2.5>
  63.   401016:        68 00 00 00 00               pushq  $0x0
  64.   40101b:        e9 e0 ff ff ff               jmpq   401000 <__abi_tag+0xcc0>

  65. Disassembly of section .text:

  66. 0000000000401020 <main>:
  67.   401020:        55                           pushq  %rbp
  68.   401021:        48 89 e5                     movq   %rsp,%rbp
  69.   401024:        48 8d 05 d5 0f 00 00         leaq   0xfd5(%rip),%rax        # 402000 <_start+0xfc0>
  70.   40102b:        48 89 c7                     movq   %rax,%rdi
  71.   40102e:        e8 dd ff ff ff               callq  401010 <puts@plt>
  72.   401033:        b8 00 00 00 00               movl   $0x0,%eax
  73.   401038:        5d                           popq   %rbp
  74.   401039:        c3                           retq
  75.   40103a:        66 0f 1f 44 00 00            nopw   0x0(%rax,%rax,1)

  76. 0000000000401040 <_start>:
  77.   401040:        f3 0f 1e fa                  endbr64
  78.   401044:        31 ed                        xorl   %ebp,%ebp
  79.   401046:        49 89 d1                     movq   %rdx,%r9
  80.   401049:        5e                           popq   %rsi
  81.   40104a:        48 89 e2                     movq   %rsp,%rdx
  82.   40104d:        48 83 e4 f0                  andq   $0xfffffffffffffff0,%rsp
  83.   401051:        50                           pushq  %rax
  84.   401052:        54                           pushq  %rsp
  85.   401053:        45 31 c0                     xorl   %r8d,%r8d
  86.   401056:        31 c9                        xorl   %ecx,%ecx
  87.   401058:        48 c7 c7 20 10 40 00         movq   $0x401020,%rdi
  88.   40105f:        ff 15 93 2f 00 00            callq  *0x2f93(%rip)        # 403ff8 <__libc_start_main@GLIBC_2.34>
  89.   401065:        f4                           hlt
  90. $
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-20 12:18:20 | 显示全部楼层


原来,没有头文件  真的能运行呀
  1. int        printf (const char *__restrict, ...);
  2. double sqrt (double);

  3. int main()
  4. {
  5.     printf("a+b=%lf\n",sqrt(15));
  6.     return 0;
  7. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 12:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表