我刚刚开始学习C(来自C#背景。)对于我的第一个程序,我决定创建一个计算因子的程序。我需要将指针传递给函数,然后更新相应的变量。
我收到错误'findFactors的冲突类型',我认为这是因为我没有表明我希望在声明findFactors函数时将指针作为参数传递。任何帮助将不胜感激!
#include <stdio.h>
#include <stdlib.h>
int *findFactors(int, int);
int main (int argc, const char * argv[])
{
int numToFind;
do {
printf("Enter a number to find the factors of: ");
scanf("%d", &numToFind);
} while (numToFind > 100);
int factorCount;
findFactors(numToFind, &factorCount);
return 0;
}
int *findFactors(int input, int *numberOfFactors)
{
int *results = malloc(input);
int count = 0;
for (int counter = 2; counter < input; counter++) {
if (input % counter == 0){
results[count] = counter;
count++;
printf("%d is factor number %d\n", counter, count);
}
}
return results;
}
答案 0 :(得分:3)
更改声明以匹配定义:
int *findFactors(int, int *);
答案 1 :(得分:2)
我为添加另一个答案而道歉,但我认为没有人涵盖您的问题中需要涵盖的每一点。
1)每当您使用malloc()
动态分配一些内存时,您必须在完成后free()
。操作系统通常会在您之后整理,但考虑到您的可执行文件中有一个使用某些内存的进程。完成所述过程后,如果您free()
该内存中的进程有更多内存可用。这是关于效率的。
正确使用免费:
int* somememory = malloc(sizeyouwant * sizeof(int));
// do something
free(somememory);
易。
2)每当您使用malloc
时,正如其他人所指出的那样,实际分配以字节为单位,因此您必须malloc(numofelements*sizeof(type));
。还有另一个使用不太广泛的函数calloc
看起来像这个calloc(num, sizeof(type));
,可能更容易理解。 calloc也会将你的内存初始化为零。
3)您不需要转换malloc
的返回类型。我知道有很多编程书籍建议你这样做,C ++要求你必须这样做(但在C ++中你应该使用new
/ delete
)。请参阅this question。
4)您的功能签名确实不正确 - 功能签名必须与其功能相匹配。
5)从函数返回指针时,我不鼓励这样做,但本身并没有错。要提两点:始终牢记1)。我asked到底是什么问题,它基本上归结为跟踪那些free()
来电。作为一个更高级的用户,还需要担心分配器类型。
这里的另一点是,考虑这个功能:
int* badfunction()
{
int x = 42;
int *y = &x;
return y;
}
这是坏事,坏事,坏事。这里发生的是我们创建并返回一个指向x
的指针,该指针只有在badfunction
时才存在。当您返回时,您有一个不再存在的变量的地址,因为x
通常是在堆栈上创建的。随着时间的推移,你会对此有更多了解;就目前而言,只要认为变量不存在于其功能之外。
请注意int* y = malloc(...
是一个不同的情况 - 因为malloc而在堆上创建了内存,因此在所述函数结束时存活。
我建议将什么作为功能签名?我实际上会稍微修改一下shybovycha的功能:
int findFactors(int* factors, const int N);
我的变化只是个人偏好。我使用const
以便我知道某些东西是函数输入的一部分。仅使用int并不是绝对必要的,但是如果你传入指针,请记住源内存可以被修改,除非你在它之前使用const
,如果你试图修改它,你的编译器应该警告你。所以在这种情况下它只是习惯。
第二个变化是我更喜欢左边的输出参数,因为我总是这么想,即output = func(input)
。
为什么在使用指针时可以修改函数参数?因为你已经传递了一个指向变量的指针。这只是一个内存地址 - 当我们“取消引用”它(访问该地址的值)时,我们可以修改它。从技术上讲,C严格按价值传递。指针本身就是包含内存地址的变量,这些变量的内容被复制到您的函数中。所以普通变量(比如int
)只是你传入的任何内容的副本。int* factors
是你传入的指针变量中地址的副本。按照设计,原始副本和副本指向相同的内存,所以当我们取消引用它们时,我们可以在调用者和原始函数中编辑该内存。
我希望能够解决一些问题。
答案 2 :(得分:1)
编辑:C中没有引用(C ++特性)
不要忘记修改方法中的numberOfFactors(如果没用,则删除此参数)。文件开头的签名也必须与最后的实现签名相匹配(这是您收到的错误)。
最后,您的malloc结果不正确。你需要这样做:
int *results = malloc(input * sizeof(int));
答案 3 :(得分:0)
int* ip <- pointer to a an int
int** ipp <- pointer to a pointer to an int.
答案 4 :(得分:0)
int *findFactors(int, int);
行说你想从这个函数返回指针(最好使用更接近类型名称的星号:int* moo();
- 这可以防止我认为的误解。)
如果你想动态改变函数参数(这比返回指针更好),你应该只使用参数,就像你已经有了这个变量一样。
最后一个错误:malloc(X)
分配X
字节,所以如果你想为某个数组分配内存,你应该使用malloc(N * sizeof(T));
,其中N
是数组的大小,T
是其类型。例如:如果你想要int *a
,你应该这样做:int *a = (int*) malloc(10 * sizeof(int));
。
现在这是你的代码,修复了(就我而言):
#include <stdio.h>
#include <stdlib.h>
int findFactors(int, int*);
int main(int argc, char **argv)
{
int numToFind, *factors = 0, cnt = 0;
do
{
printf("Enter a number to find the factors of: ");
scanf("%d", &numToFind);
} while (numToFind > 100);
cnt = findFactors(numToFind, factors);
printf("%d has %d factors.\n", numToFind, cnt);
return 0;
}
int findFactors(int N, int* factors)
{
if (!factors)
factors = (int*) malloc(N * sizeof(int));
int count = 0;
for (int i = 2; i < N; i++)
{
if (N % i == 0)
{
factors[count++] = i;
printf("%d is factor number #%d\n", i, count);
}
}
return count;
}
注意:不要忘记随时初始化你的指针(正如我所做的那样)。如果你想调用函数,将指针作为参数传递,则必须至少在函数调用之前确保它的值为0
。否则,您将收到运行时错误。