【问题标题】:Function pointer as a member of a C struct函数指针作为 C 结构的成员
【发布时间】:2010-11-23 22:28:45
【问题描述】:

我有一个如下结构,它带有一个指向名为“length”的函数的指针,该函数将返回 chars 成员的长度。

typedef struct pstring_t {
    char * chars;
    int (* length)();
} PString;

我有一个函数可以从指向 PString 的指针返回字符的长度:

int length(PString * self) {
    return strlen(self->chars);
}

我有一个函数 initializeString(),它返回一个指向 PString 的指针:

PString * initializeString() {
    PString *str;
    str->length = &length;
    return str;
}

很明显,我在这里的指针做错了什么,因为str->length = &length 行在我的调试器中导致了 EXC_BAD_ACCESS 信号,`return strlen(self->chars) 也是如此。有人对这个问题有任何见解吗?

我特别希望能够让 initializeString() 函数返回指向 PString 的指针,并让 length 函数使用指向 PString 的指针作为输入。这只是在 C 中实现一个基本的面向对象系统的一个实验,但我没有太多正面处理指针的经验。感谢您能给我的任何帮助。

【问题讨论】:

  • 虽然你说你特别想返回一个指针。在这种情况下,返回结构本身要好得多。复制结构很便宜,并且不需要重的堆分配。字符串对象是基于值的:它们没有身份(地址),但它们的相等性基于它们的内容。不知何故,你也可以在你的 OOP 系统中拥有这种与众不同的感觉。

标签: c function pointers


【解决方案1】:

分配内存来保存字符。

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

typedef struct PString {
        char *chars;
        int (*length)(PString *self);
} PString;

int length(PString *self) {
    return strlen(self->chars);
}

PString *initializeString(int n) {
    PString *str = malloc(sizeof(PString));

    str->chars = malloc(sizeof(char) * n);
    str->length = length;

    str->chars[0] = '\0'; //add a null terminator in case the string is used before any other initialization.

    return str;
}

int main() {
    PString *p = initializeString(30);
    strcpy(p->chars, "Hello");
    printf("\n%d", p->length(p));
    return 0;
}

【讨论】:

  • 很好的答案!问题:我需要调用 free(p),但我还需要释放字符吗?
  • malloc 的返回值不需要在 C 中强制转换。另外,你应该在分配之后初始化str-&gt;chars(即str-&gt;chars[0] = '\0';)。
  • 函数指针int (* length)()是否需要/不需要识别PString *参数?
  • @ephemera 有道理。您必须使用函数的完整原型。我尝试没有在 PString 结构中指定函数的参数,但出现错误。如果我写 int (* length)(PString *self);,它工作正常。
  • 为什么initializeString使用str-&gt;length = length;而不是str-&gt;length = &amp;length;?它会自动减少为具有该用法的指针吗?
【解决方案2】:

我的猜测是您的部分问题是参数列表不匹配。

int (* length)();

int length(PString * self)

不一样。应该是int (* length)(PString *);

...哇,是乔恩!

编辑:而且,如下所述,你的结构指针永远不会被设置为指向任何东西。你这样做的方式只有在你声明一个普通的结构而不是一个指针时才有效。

str = (PString *)malloc(sizeof(PString));

【讨论】:

  • 非常感谢,雅各布。我会继续尝试。
  • 好的,strlen(self-&gt;chars) 仍然给我EXC_BAD_ACCESS
【解决方案3】:

也许我在这里遗漏了一些东西,但是您在访问该 PString 之前是否为它分配了任何内存?

PString * initializeString() {
    PString *str;
    str = (PString *) malloc(sizeof(PString));
    str->length = &length;
    return str;
}

【讨论】:

  • 请停止投射malloc。不需要在 C 中这样做。
  • 更好地处理所有警告。
【解决方案4】:

永远不会分配指针str。使用前应该是malloc'd。

【讨论】:

  • PString *str = (PString *)malloc(sizeof(PString)); 替换PString *str; 理想情况下,使用指针调用free 以避免内存泄漏。
【解决方案5】:

您也可以使用“void*”(void 指针)向函数发送地址。

typedef struct pstring_t {
    char * chars;
    int(*length)(void*);
} PString;

int length(void* self) {
    return strlen(((PString*)self)->chars);
}

PString initializeString() {
    PString str;
    str.length = &length;
    return str;
}

int main()
{
    PString p = initializeString();

    p.chars = "Hello";

    printf("Length: %i\n", p.length(&p));

    return 0;
}

输出:

Length: 5

【讨论】:

  • 当心!这会导致未定义的行为,因为initializeString() 中的变量PString str; 不存在,当您通过main() 中的指针访问它时。
  • 正如@Kupto 提到的,因为您没有将内存分配给函数的指针,所以真的不知道您的程序到底要做什么。我建议让 initializestring 方法返回一个指向类型的 ptr,然后在返回它之前,将指针分配给函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多