Function pointer as a member of a C struct

CFunctionPointers

C Problem Overview


I have a struct as follows, with a pointer to a function called "length" that will return the length of the chars member.

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

I have a function to return the length of the characters from a pointer to a PString:

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

I have a function initializeString() that returns a pointer to a PString:

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

It is clear that I am doing something very wrong with my pointers here, because the str->length = &length line causes an EXC_BAD_ACCESS signal in my debugger, as does `return strlen(self->chars). Does anyone have any insights into this problem?

I specifically want to be able have the initializeString() function return a pointer to a PString, and the length function to use a pointer to a PString as input. This is just an experiment in implementing a rudimentary object-oriented system in C, but I don't have a lot of experience dealing with pointers head-on. Thanks for any help you can give me.

C Solutions


Solution 1 - C

Allocate memory to hold chars.

#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;
}

Solution 2 - C

My guess is that part of your problem is the parameter lists not matching.

int (* length)();

and

int length(PString * self)

are not the same. It should be int (* length)(PString *);.

...woah, it's Jon!

Edit: and, as mentioned below, your struct pointer is never set to point to anything. The way you're doing it would only work if you were declaring a plain struct, not a pointer.

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

Solution 3 - C

Maybe I am missing something here, but did you allocate any memory for that PString before you accessed it?

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

Solution 4 - C

The pointer str is never allocated. It should be malloc'd before use.

Solution 5 - C

You can use also "void*" (void pointer) to send an address to the function.

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;
}

Output:

Length: 5

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJonathan SterlingView Question on Stackoverflow
Solution 1 - CKV PrajapatiView Answer on Stackoverflow
Solution 2 - CjtbandesView Answer on Stackoverflow
Solution 3 - CEdHView Answer on Stackoverflow
Solution 4 - CjgottulaView Answer on Stackoverflow
Solution 5 - Contech7View Answer on Stackoverflow