Home > Enterprise >  prototype of a struct in c
prototype of a struct in c

Time:04-04

I'd like to organize my code in c, so it works a little bit like the public and private keywords in c

specifically, I have some functions that will be used as a library in other projects, and I would like to make public only the functions that are used by the projects, not the functions necessary for the internal actions

it would be easy if I could have all of them in the same file.c, but my school rules prevent me against that

I hope an example will be clear :

(A) struct definition      (B) struct definition
in header.h                in second_file.c
 ----------------------     ---------------------- 
| header.h             |   | header.h             |
------------------------   ------------------------
| #ifndef HEADER_H     |   | #ifndef HEADER_H     |
| # define HEADER_H    |   | # define HEADER_H    |
|                      |   |                      |
| typedef struct foo   |   |                      |
| {                    |   |                      |
|   type param_1;      |   |                      |
|   type param_2;      |   |                      |
| } t_foo;             |   |                      |
|                      |   |                      |
| void action_a(void); |   | void action_a(void); |
| void action_b(void); |   | void action_b(void); |
|                      |   |                      |
| #endif               |   | #endif               |
 ----------------------     ---------------------- 

 ----------------------     ---------------------- 
| first_file.c         |   | first_file.c         |
------------------------   ------------------------
| # include header.h   |   | #include header.h    |
|                      |   |                      |
| // prototypes        |   | // prototypes        |
| void utils_a(void);  |   | void utils_a(void);  |
| void utils_b(void);  |   | void utils_b(void);  |
|                      |   |                      |
|                      |   | // struct prototype  |
|                      |   | t_foo;               |
|                      |   |                      |
| void action_a(void){ |   | void action_a(void){ |
|   // do something;   |   |   // do something;   |
|   // use t_foo;      |   |   // use t_foo;      |
| }                    |   | }                    |
| void action_b(void){ |   | void action_b(void){ |
|   // do something;   |   |   // do something;   |
| }                    |   | }                    |
 ----------------------     ---------------------- 

 ----------------------     ---------------------- 
| second_file.c        |   | second_file.c        |
------------------------   ------------------------
| # include header.h   |   | #include header.h    |
|                      |   |                      |
|                      |   | typedef struct foo   |
|                      |   | {                    |
|                      |   |   type param_1;      |
|                      |   |   type param_2;      |
|                      |   | } t_foo;             |
|                      |   |                      |
| void utils_a(void) { |   | void utils_a(void) { |
|   // do something;   |   |   // do something;   |
|   // use t_foo;      |   |   // use t_foo;      |
| }                    |   | }                    |
| void utils_b(void) { |   | void utils_b(void) { |
|   // do something;   |   |   // do something;   |
| }                    |   | }                    |
 ----------------------     ---------------------- 

case A works, but not case B

as you can see, in both cases (A and B) the header doesn't include the utils functions, they cannot be used by other functions (unless they include the prototype themselves), the header doesn't include them

I would like to do the same for the struct (which is used in both files.c), because this struct is only a utility for the functions, but has no purpose to be called elsewhere

EDIT a working example with solution from comments, but its not working (compilation gives me an error)

header.h

#ifndef HEADER_H
# define HEADER_H

#include <stdlib.h> // malloc()
#include <stdio.h>  // printf()

// CASE A ONLY
// typedef struct  foo {
//     int         param;
// }               t_foo;
// CASE A END

// CASE B ONLY
typedef struct  foo t_foo;
// CASE B END

t_foo   **allocate_foo(void);

#endif

first_file.c

#include "header.h"

int     main(void)
{
        t_foo   **tfoo;

        tfoo = allocate_foo();
        (*tfoo)->param = 1;
        printf("%i\n", (*tfoo)->param);
        return (0);
}

second_file.c

#include "header.h"

// CASE B ONLY
struct  foo {
        int     param;
};
// CASE B END

t_foo   **allocate_foo(void)
{
        static t_foo    *tfoo;

        tfoo = malloc(sizeof(t_foo));
        return (&tfoo);
}

case A compiles fine and prints 1, but case B throw an error at compilation :

first_file.c: In function ‘main’:
first_file.c:8:9: error: dereferencing pointer to incomplete type ‘t_foo {aka struct foo}’
  (*tfoo)->param = 1;
         ^~

CodePudding user response:

The usual most basic solution is to make public the struct type identifier, but keep the definition private ... aka opaque pointer ... something like FILE

/* library.h */
#ifndef LIBRARY_H_INCLUDED
#define LIBRARY_H_INCLUDED

struct foo; // struct foo exists; it's definition is elsewhere
struct foo *newfoo(int);
void printfoo(struct foo *);
void killfoo(struct foo *);

#endif // LIBRARY_H_INCLUDED

/* library.c */
#include <stdio.h>
#include <stdlib.h>
#include "library.h"

struct foo { int bar; }; // struct foo has a single member

struct foo *newfoo(int n) {
    struct foo *r = malloc(sizeof *r);
    if (r) r->bar = n;
    return r;
}

void printfoo(struct foo *s) {
    printf("%d\n", s->bar);
}

void killfoo(struct foo *s) {
    free(s);
}

/* main.c */
#include "library.h"

int main(void) {
    struct foo *p = newfoo(42);
    if (p) {
        printfoo(p);
        killfoo(p);
    }
    return 0;
}
  • Related