为什么从函数返回数组时会收到警告?

时间:2016-12-16 18:22:06

标签: c

我已经看到了一些在stackoverflow上从函数返回数组的例子。我按照这些例子,但我仍然收到警告。

#include <stdio.h>
#include <stdlib.h>

char * getNum();

int main(){

    int * num;
    int * i;

    num = getNum();
    puts(num);

    return 0;
}

char * getNum(){

    FILE * fp;
    fp = fopen("number", "r");      //getting a 1000 digit number from a file
    char * n;                       //putting it in "array"
    n = (char *)malloc(1000 * sizeof(char));
    char x[100];
    int i, j = 0;

    while(!feof(fp)){
        fgets(x, 100, fp);
        for(i=0; i<50; i++){        //getting the first 50 characters in a line
            n[j] = x[i];            //to avoid "new line"
            j++;
        }
    }
    fclose(fp);
    n[1000] = '\0';

    return n;
}
如果我忽略警告,

puts(num)给出正确的号码? 他们为什么会出现? 我希望这不是重复的。

cc     8.c   -o 8
8.c: In function ‘main’:
8.c:11:9: warning: assignment from incompatible pointer type
     num = getNum();
         ^
8.c:12:10: warning: passing argument 1 of ‘puts’ from incompatible pointer type
     puts(num);
          ^
In file included from 8.c:1:0:
/usr/include/stdio.h:695:12: note: expected ‘const char *’ but argument is of type ‘int *’
 extern int puts (const char *__s);
            ^

3 个答案:

答案 0 :(得分:5)

问题在于您似乎将调用getNum的结果分配给int *类型的变量,这在getNum返回{{1}时没有多大意义}}。

您还尝试使用char *打印puts类型的变量,而int *只接受puts

更重要的是,你已经在函数代码中超出界限,正如我在评论中已经提到的那样:const char *为1000个字符分配内存。 n = (char *)malloc(1000 * sizeof(char));尝试访问第1001个(!)字符。请记住,数组索引从零开始!

答案 1 :(得分:3)

n = (char *)malloc(1000 * sizeof(char)); // ugly code

那应该是

 n = malloc(1000);
 if (n==NULL) {perror("malloc"); exit(EXIT_FAILURE);};

因为sizeof(char) 总是 1,并且因为你不应该(在C中)投射malloc的结果,并且因为malloc 可以失败你应该对此进行测试。

然后你再做一次

   n[1000] = '\0'; // wrong code

这改变了1001 -th 字节(最后1000 -th 一个),所以是undefined behavior(它是buffer overflow)。你应该是really scared,可能会发生坏事(如果他们不这样做,那是因为你不幸)。你可能想要

 n[999] = '\0'; // the 1000th byte

顺便说一句,我猜你在某些类似POSIX的系统上使用GCCClang。你真的应该养成使用所有警告和调试信息进行编译的习惯:

cc   -Wall -g  8.c   -o 8

(如果使用make,您可能需要CFLAGS= -Wall -g中的Makefile

您可能想了解有关instrumentation options的更多信息,例如:您也可以将-fsanitize=address传递给gcc

然后您可以使用gdb调试器,也可以使用valgrind。但是一定要改进自己的代码,直到没有警告为止。

当然num = getNum();不正确。您正在将指针指定为整数(因此您的类型不匹配)。这通常是错误的(并且在罕见的情况下 - 不是在这里 - 你真的是这个意思,你应该有一些显式的强制转换来向读者展示你的代码 - 也许你明年 - 你真正想做的事情。)

您希望字符串转换为数字。阅读更多documentationC standard library。您想使用atoi(在终端中输入man atoi,或阅读atoi(3)),然后输入代码:

num = atoi(getNum());

你也在编码:

while(!feof(fp)) // bad code

这是错误的(有点棘手,请参阅this)。 <{1}}仅在某些读取操作后有效(而之前不是,请参阅feof(3))。因为您想删除结尾feof(但请阅读fgets(3)&amp; strchr(3) ...),您可能需要

\n

最后你的代码也不正确,因为 do { if (NULL==fgets(x, 100, fp)) break; char*eol = strchr(x, '\n'); if (eol) *eol = 0; } while (!feof(fp)); 没有初始化返回的内存区域。所以你的malloc可能在某个意想不到的地方有一个零字节。

也许您应该阅读(POSIX特定的)strdup(3)getline(3)。两者都可以使您的代码更简单。并考虑具有很长行的文件的不利情况(您可能有一个包含数千字节行的文件,您甚至可以拥有一个没有任何换行符的文件)。

您的n也是错误的,因为类型不匹配。考虑使用printf(3)(但习惯是使用puts(num)结束控制格式字符串,或者使用fflush(3)因为\n 缓冲),所以<stdio.h>

答案 2 :(得分:2)

问题是您要将vector<A*>类型的指针分配给char *类型的指针,因此指定“ INCOMPATIBLE ”指针。

您还试图将int *指针传递给期望int *指针的puts(),因此还有另一个警告。

你为什么要这样做?如果它们是不同类型的明确指针,那么无论如何你尝试它都是非常奇怪的。

如果您认为出于某种原因这是正确的,那将会很有趣。

您需要仔细阅读警告并尝试理解它们的含义,这将有助于您学习很多基础知识和良好实践。

此外,请注意:while (!feof(fp))不是检查是否有其他内容无法阅读的好方法,因为char *需要先失败(尝试fgets()之后的读取)因此,在读取错误后仍然会执行EOF循环。您应该更改为for (i ...)

最后,在中,没有必要将while (fget(x, 100, fp) != NULL)强制转换为任何其他poitner类型,并且由于原因{{void *而转换malloc()的返回值被认为是不好的做法3}}