在C语言中-如何定义以指针作为参数的函数?

时间:2019-03-13 16:07:34

标签: c function pointers

我试图定义一个名为scanEntries的函数,该函数需要一个int参数和一个指针参数。当我尝试编译它时,出现错误消息:

"warning: passing argument 2 of ‘scanEntries’ makes pointer from integer 
 without a cast [enabled by default]"

我尝试在此处查找该错误消息,但我得到的只是有关现有字符串相关函数的结果,而不是定制功能。我以前从未尝试过将指针作为参数编写函数。我究竟做错了什么?到底需要在这里强制投放什么?我该怎么办?

 /* function to scan any integer value */
int scanInt() {
    int output;
    scanf("%d\n", output);
    return(output);
}

/* scanInt but as one entry out of a group */
int scanEntry(int number, int total) {
    printf("Please enter score %d of %d: ", number+1, total);
    return(scanInt());
}

/* scanEntry for an entire dynamic array) */
void scanEntries(int total, int *p) {
    int number;
    for(number = 0; number < total; number++) {
        *(p + number) = scanEntry(number, total);
        /* for testing */
        printf("%d", *(p + number));
    }
}

这里是调用scanEntries的地方,加上上面没有显示的我在这里使用的其他功能:

/* scanInt but with a prompt to enter size */
int enterSize() {
    printf("Please enter size of array: ");
    return(scanInt());
}

int main() {
    /* entering initial size, done in a separate function */
    int initSize = enterSize();
    int *p; /* p is an int pointer */
    p = calloc(initSize, sizeof(int));
    printf("%d", initSize);

    scanEntries(enterSize(), *p);
}

4 个答案:

答案 0 :(得分:1)

这是如何操作的基本要点:

  • 声明一个接受指针的函数
  • 将指针传递给函数

最小示例:

3.x

它输出#include <stdio.h> void incrementMyInt(int *p) { // increment the value of the int that p points to (*p)++; } int main() { int n1 = 3; int *n2 = malloc(sizeof(int)); *n2 = 7; incrementMyInt(&n1); // pass the address of n incrementMyInt(n2); printf("n1 is %d\n", n); printf("n2 is %d\n", *n2); return 0; } n1 is 4

答案 1 :(得分:1)

更改:

scanEntries(enterSize(), *p);

收件人:

scanEntries(enterSize(), p);

说明

您必须传递一个指针作为函数的第二个参数。 p是一个指向int的指针,因此,您进行的调用传递了int而不是指针。这就是为什么要发出警告。

答案 2 :(得分:1)

函数的定义很好。问题是你怎么称呼它。

main函数中,您将p声明为指针:

int *p; /* p is an int pointer */

但是随后在调用scanEntries时会取消引用该指针:

scanEntries(enterSize(), *p);

您实际上是在向函数传递int而不是指向int的指针,因此编译器正在尝试将int转换为指针以匹配参数。这就是警告告诉你的。

由于该函数需要一个int *,因此只需将其直接传递给该函数即可。另外,由于您已经拥有大小,因此无需在此处再次调用enterSize。使用initSize代替:

scanEntries(initSize, p);

而且,这是错误的:

scanf("%d\n", output);

%d格式说明符期望指向int的指针,但是您只是在传递普通的int。为格式说明符使用错误的类型会调用undefined behavior

您想将output的地址传递给该函数,以使其得到更新。另外,格式中的\n将使您的程序提示您进行额外的输入。不需要。

scanf("%d", &output);

答案 3 :(得分:0)

从我的评论继续-如果您声明int *p;并且您的原型是void scanEntries(int total, int *p),您可以简单地将其称为scanEntries(initSize, p);(此处没有'*'"warning: passing argument 2 of ‘scanEntries’ makes pointer from integer without a cast [enabled by default]"是由于您尝试传递*p从而取消了对整数的引用指针'p'产生一个int值,而不是一个 int指针

除了最初的指针传递问题之外,您还有大量附加错误:

main()中,您不应第二次致电enterSize()

    scanEntries (initSize, p);

此外,您必须验证每个分配和每个输入,例如

    p = calloc(initSize, sizeof(int));
    if (!p) {   /* VALIDATE EVERY ALLOCATION */
        perror ("calloc-p");
        return 1;
    }

最后,如果您分配了内存,请养成良好的习惯,并确保free在不再需要时使用它,例如

    free (p);   /* don't forget to free what you allocate */
}

scanInt()中,您必须提供指向{{1}的output的指针,例如

scanf

注意 if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */ fputs ("error: invalid input - not an integer.\n", stderr); exit (EXIT_FAILURE); } 通话中的&output

此外,尽管等效,但不要对scanf使用指针表示法,而只需使用*(p + number),它更易读。

完全将其放入,您可以这样做:

p[number]

使用/输出示例

注意:您可以在编译器选项中添加#include <stdio.h> #include <stdlib.h> /* function to scan any integer value */ int scanInt (void) { int output; if (scanf ("%d", &output) != 1) { /* VALIDATE EVERY INPUT */ fputs ("error: invalid input - not an integer.\n", stderr); exit (EXIT_FAILURE); } return (output); } /* scanInt but as one entry out of a group */ int scanEntry (int number, int total) { printf ("Please enter score %d of %d: ", number+1, total); return (scanInt()); } /* scanEntry for an entire dynamic array) */ void scanEntries (int total, int *p) { int number; for (number = 0; number < total; number++) { p[number] = scanEntry (number, total); #ifdef TESTING printf (" scanEntries testing - %d\n", p[number]); #endif } } /* scanInt but with a prompt to enter size */ int enterSize (void) { printf ("Please enter size of array: "); return (scanInt()); } int main (void) { /* entering initial size, done in a separate function */ int initSize = enterSize(), *p; /* p is an int pointer */ p = calloc(initSize, sizeof(int)); if (!p) { /* VALIDATE EVERY ALLOCATION */ perror ("calloc-p"); return 1; } printf ("%d\n", initSize); scanEntries (initSize, p); printf ("%d entries read:\n\n", initSize); for (int i = 0; i < initSize; i++) printf ("p[%2d] : %d\n", i, p[i]); free (p); /* don't forget to free what you allocate */ } ,以定义-DTESTING来激活其他代码。)

TESTING

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时可以释放

当务之急是使用一个内存错误检查程序来确保您不会尝试访问内存或在已分配的块的边界之外/之外进行写入,不要试图以未初始化的值读取或基于条件跳转,最后,以确认您释放了已分配的所有内存。

对于Linux,$ ./bin/scanentries Please enter size of array: 4 4 Please enter score 1 of 4: 1 Please enter score 2 of 4: 2 Please enter score 3 of 4: 3 Please enter score 4 of 4: 4 4 entries read: p[ 0] : 1 p[ 1] : 2 p[ 2] : 3 p[ 3] : 4 是正常选择。每个平台都有类似的内存检查器。它们都很容易使用,只需通过它运行程序即可。

valgrind

始终确认已释放已分配的所有内存,并且没有内存错误。

仔细检查一下,如果还有其他问题,请告诉我。