【问题标题】:multifile direct compile ok, direct compile errormultifile直接编译ok,直接编译报错
【发布时间】:2020-02-13 20:45:21
【问题描述】:

有 3 个文件(generator.c、generator.h 和 main.c)。

generator.c:generator.c 中只有 1 个函数(gen fun)用于生成一个数组来存储 10 个随机生成的数字。

generator.h:generator.c 的声明

main.c:main.c中只有1个函数(main fun),用于打印之前生成的数字。

如果 generator.c 包含在 main.c 中,我通过执行“gcc main.c”直接编译它。结果还可以。

但是当我使用“gcc -c generator.h,gcc -c main.c,gcc generator.o main.o”编译它时,它报告了一个警告“warning:在主函数中的“p = gen(arr);”语句中,赋值使指针在没有强制转换的情况下从整数生成"。最终结果是“Segmentation fault (core dumped)”。如果我尝试在 main 函数的 while 循环中访问指针 *p(即数组 [0]) 的值,则调试信息显示“无法访问地址处的内存”。

//////generator.c///////
int *  gen( int arr[])
{
    int i = 0;
    int * p = arr;
    int len = 10;
    srand( (unsigned)((time)(NULL)));
    while (i< len)
    {
        *p = rand() % ( len  +1) + 0;
        i ++;
        p++;
    }
    return arr;
}

//////generator.h//////
int * gen( int arr[]);

//////main.c///////
int main(void)
{
    int i = 0;
    int arr[10]={0};
    int * p;
    p = gen(arr);

    while (i < 10)
    {
        printf("output is %d\n",*p);// Segmentation fault (core dumped)
        i++;
        p++;
    }
    return 0;
}

【问题讨论】:

  • 我第二次看到*p = rand() % ( len +1) + 0; -- 你确定 -- 你不是说*p = rand() % len + 1; 吗? (在1 &lt;= *p &lt;= 10 之间生成随机数)?您的代码没有其他问题(这本身并没有错,只是不稳定)
  • "但是当我使用 "gcc -c generator.h" 编译它时 --- 不要在你的编译字符串中包含 generator.h....
  • @DavidC.Rankin 实际上,这是我第二次提交这个问题,因为之前的代码包含一些错误......我看到代码示例为“ int num = (rand() % (上 - 下 + 1)) + 下”。至于代码,我不明白为什么没有编译错误而是最终输出错误。
  • 是的,这是一个 Range + Offset 用于不从零开始的范围。 rand() % (limit + 1)(给出0 &lt;= n &lt;= limit 的范围)和rand() % limit + 1;(给出1 &lt;= n &lt;= limit 的范围)之间的区别,所以你需要什么真的很重要。
  • @DavidC.Rankin 感谢您的及时回复!多文件编译真的让我很困惑。在一个文件中获取所有功能时,编译过程非常简单。但是我正在尝试练习如何编写makefile来编译C的多个文件。显然我是C语言的新手,如果你能推荐一些C学习的书籍,对我很有帮助。

标签: c makefile segmentation-fault core


【解决方案1】:

根据您对问题的补充,您似乎对如何包含 generator.h 然后编译代码感到困惑。首先你的generator.h 应该是:

//////generator.h//////
#ifndef GENERATOR_H
#define GENERATOR_H  1

int *gen (int arr[]);

#endif

edit: 添加了适当的Header Guards 以防止多次包含generator.h

您的generator.c 将是:

//////generator.c///////
#include <stdlib.h>

#include "generator.h"

int *gen (int arr[])
{
    int i = 0;
    int * p = arr;
    int len = 10;

    while (i< len)
    {
        *p = rand() % len + 1;
        i ++;
        p++;
    }

    return arr;
}

最后你的main.c(我称之为gen.c)将是:

//////main.c///////
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "generator.h"

int main(void)
{
    int i = 0;
    int arr[10]={0};
    int *p;

    srand( (unsigned)((time)(NULL)));

    p = gen(arr);

    while (i < 10)
    {
        printf ("output is %d\n",*p);
        i++;
        p++;
    }
    return 0;
}

编译

$ gcc -Wall -Wextra -pedantic -std=c11 -Ofast generator.c -o bin/gen gen.c

注意:我还鼓励将-Wshadow 添加为编译字符串的正常部分,以识别任何阴影变量)

使用/输出示例

$ ./bin/gen
output is 8
output is 1
output is 5
output is 4
output is 9
output is 5
output is 4
output is 6
output is 5
output is 6

查看一下,如果您还有其他问题,请告诉我。

【讨论】:

  • 一个很好的答案,除了一些细节。特别是不要在头文件中包含头文件,除非该头文件的内容需要它们。文件generator.h 不需要#include &lt;stdlib.h&gt; 也不需要#include &lt;time.h&gt; 此外,对srand() 的调用只能进行一次,通常在函数的顶部:main()
  • 这些都是好点。我们可以将它们移到需要它们的来源中。
  • (最初的答案是展示如何编译提问者所拥有的内容)正确的重新排列并没有被卡住。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 2012-11-21
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多