声明返回指针的函数

时间:2016-10-30 23:56:04

标签: c pointers

这是我的代码:

#include <stdio.h>

struct entry
{
    int value;
    struct entry *next;
};

struct entry * findEntry (struct entry *listPtr, int match)
{
    while (listPtr != (struct entry *) 0)
        if (listPtr->value == match)
            return (listPtr);
        else
            listPtr = listPtr->next;

    return (struct entry *) 0;
}

int main(void)
{
    struct entry * findEntry(struct entry * listPtr, int match);
    struct entry n1, n2, n3;
    struct entry * listPtr, *listStart = &n1;

    int search;

    n1.value = 100;
    n1.next  = &n2;

    n2.value = 200;
    n2.next  = &n3;

    n3.value = 100;
    n3.next  =   0;

    printf("Enter value to locate: ");
    scanf ("%i", &search);

    listPtr = findEntry (listStart, search);

    if (listPtr != (struct entry *) 0)
        printf( "Found %i.\n", listPtr->value);
    else
        printf("Not found.\n");

    return 0;
}

所以对于这一行:

struct entry *findEntry (struct entry *listPtr, int match) 

为什么在查找条目前面有*?因为它应该是一个函数声明,但*findEntry是一个指针?我根本不明白这句话是什么......

在书中解释是:指定函数findEntry()返回一个指向条目结构的指针,并且它将这样的指针作为其第一个参数,将整数作为其第二个

在这种情况下需要*符号吗?

谢谢

3 个答案:

答案 0 :(得分:1)

想象一下有人告诉你,23+45等于275,然后通过以下逻辑对其进行解释:我们必须单独计算3+4并保持2和{{两边都没有变化。当然,这没有任何意义。 5符号的正确含义并不意味着应该将23+45片段从其中撕掉并单独处理。

当你将3+4与声明的其余部分隔离开来并得出结论它声明*findEntry作为指针时,你实际上会犯同样的错误。您的声明中没有findEntry这样的实体。声明语法规定右侧的*findEntry位首先绑定到名称(...)。然后我们才开始考虑名称左侧的findEntry

这意味着您的*声明以findEntry绑定开头,表示findEntry(...)是一个函数。只有在此之后我们才会考虑findEntry位,获取*,它告诉我们*findEntry(...)是一个返回指针的函数。

答案 1 :(得分:0)

C的语法没有为返回值提供参数名称(因为它无论如何都不能在代码中使用)。宣言:

struct entry * findEntry (struct entry *listPtr, int match)

可写:

struct entry *
findEntry (struct entry *listPtr, int match)

(实际上是在某些编码标准中以这种方式编写的)。

并且声明了一个名为findEntry的函数,它返回指向struct entry(a struct entry *)的指针。如果没有*,该函数将返回struct entry

答案 2 :(得分:0)

  

为什么在查找条目前面有*?因为它应该是一个函数声明,但*findEntry是一个指针?我根本不明白这句话是什么......

是的,它表明findEntry是一个返回指针值的函数。

C声明语法以表达式的类型为中心。例如,假设我们有一个指向int的指针,我们想要访问指向int的值。我们在指针上使用一元*运算符,如下所示:

x = *p;

表达式 *p的类型为int,因此当我们声明指针变量p时,我们会这样做

int *p;

声明符 *p指定p的“指针”。类似地,假设我们有一个函数返回指向int的指针,并且我们想再次访问指向的整数值。同样,我们对函数返回的值使用一元*运算符:

x = *f();

表达式 *f()的类型为int,所以当我们声明函数时,我们会写

int *f(void);  // void means f takes no arguments

在这种情况下,f的“function-ness”和“pointer-ness”都由声明者*f(void)给出。

现在,我们可以决定将f的返回值分配给p

p = f();

请注意,在这种情况下,我们在任一表达式上使用*运算符,因为这次我们对指针值感兴趣,不是指向的整数值。但是我们仍然需要在声明中使用*来表示它们处理指针值。

在表达式和声明语法中,后缀()[]运算符之前绑定(优先级高于)一元*运算符。因此:

T *f();     // declares f as a function returning a pointer to T
T (*f)();   // declares f as a pointer to a function returning T
T *a[N];    // declares a as an N-element array of pointer to T
T (*a)[N];  // declares a as a pointer to an N-element array of T

因此,当您发现一个有点复杂的声明时,从最左边的标识符开始,使用上面的优先规则。递归地将这些规则应用于任何函数参数。所以,鉴于你的声明

struct entry * findEntry (struct entry *listPtr, int match);

我们将其视为

               findEntry                                      -- findEntry
               findEntry (                                )   -- is a function taking
               findEntry (              listPtr           )   --   parameter listPtr
               findEntry (             *listPtr           )   --     is a pointer to
               findEntry (struct entry *listPtr           )   --     struct entry
               findEntry (struct entry *listPtr,     match)   --   parameter match
               findEntry (struct entry *listPtr, int match)   --     is an int
             * findEntry (struct entry *listPtr, int match)   -- returning a pointer to 
struct entry * findEntry (struct entry *listPtr, int match);  -- struct entry