我已经看到了一些在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);
^
答案 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的系统上使用GCC或Clang。你真的应该养成使用所有警告和调试信息进行编译的习惯:
cc -Wall -g 8.c -o 8
(如果使用make
,您可能需要CFLAGS= -Wall -g
中的Makefile
您可能想了解有关instrumentation options的更多信息,例如:您也可以将-fsanitize=address
传递给gcc
然后您可以使用gdb
调试器,也可以使用valgrind。但是一定要改进自己的代码,直到没有警告为止。
当然num = getNum();
不正确。您正在将指针指定为整数(因此您的类型不匹配)。这通常是错误的(并且在罕见的情况下 - 不是在这里 - 你真的是这个意思,你应该有一些显式的强制转换来向读者展示你的代码 - 也许你明年 - 你真正想做的事情。)
您希望将字符串转换为数字。阅读更多documentation的C 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 ...)
最后,在c中,没有必要将while (fget(x, 100, fp) != NULL)
强制转换为任何其他poitner类型,并且由于原因{{void *
而转换malloc()
的返回值被认为是不好的做法3}}