2

I want to have access to struct members myself, and don't want others to see the details. Simply I mean Protected access modifier in Java.

I have a file called linkedlist.c which has a struct like this:

struct listNode
{
    int data;
    struct listNode *next;
};

struct linkedlist
{
    ListNode *head;
};

and a header file linkedlist.h like this:

typedef struct listNode ListNode;
typedef struct linkedlist LinkedList;

but I am not able to use struct members in another file called priority_queue.c since struct definition is only in .c file.

How to implement these structs that I myself have access to members but other programmers can just see the types LinkedList and ListNode?

SMhd Asadi
  • 161
  • 12
  • 1
    You'll need two headers. One defines the public interface. The other defines the protected interface. The second should include the first to ensure consistency. Your code uses the protected interface. Everyone else’s code uses the public interface. – Jonathan Leffler Feb 09 '21 at 13:30
  • Switch to C++ and you will have this (`private` modifier in `struct`). You can keep procedure oriented programming in the same time. – i486 Feb 09 '21 at 13:49
  • 2
    Use an opaque structure: [**What is an opaque pointer in C?**](https://stackoverflow.com/questions/7553750/what-is-an-opaque-pointer-in-c) – Andrew Henle Feb 09 '21 at 13:52

2 Answers2

2

As I noted in a terse comment, I think you will need two headers (or, alternatively, I'd approach this using two headers). One header defines the public interface. The other defines the protected interface. The second should include the first to ensure consistency. Your code uses the protected interface. Everyone else’s code uses the public interface.

What I mean is that the public interface is an opaque type and the “protected” interface defines the private details. The functions in the interface will use pointers to the opaque types, so your public header might be:

linkedlist.h

#ifndef LINKEDLIST_H_INCLUDED
#define LINKEDLIST_H_INCLUDED

typedef struct listNode ListNode;
typedef struct linkedlist LinkedList;
typedef int Data;

extern LinkedList *ll_create(void);
extern ListNode *ln_create(Data value);
extern void ll_destroy(LinkedList *ll);
extern void ln_destroy(ListNode *ln);

…

#endif /* LINKEDLIST_H_INCLUDED */

You'd also have a second header which gives the protected access, call it linkedlistp.h:

#ifndef LINKEDLISTP_H_INCLUDED
#define LINKEDLISTP_H_INCLUDED

#include "linkedlist.h"

struct listNode
{
    Data data;
    ListNode *next;
};

struct linkedlist
{
    ListNode *head;
};

#endif /* LINKEDLISTP_H_INCLUDED */

Your source file linkedlist.c would include linkedlistp.h; so would any other source file that needs to be a party to the internals of the data structure. Ordinary user code would only have access to linkedlist.h and would use only the public interface, therefore.

It's mostly rebranding the private implementation details in a header that can be used by multiple privileged source files instead of being hidden in a single source file as is more usual (and as you currently have it). It doesn't enforce the separation — unless you don't distribute the private header, anybody can decide that their code is privy to the internals by including the protected header. In a project within an organization, you can institute rules to disallow the use of the protected header. If you release the code as an open source project, you can't control what people do with the protected header.

Note that the protection is 'all or nothing'; there is no half-way house. The code either knows all about the internals of the structures (because it included linkedlistp.h) or nothing about the internals of the structure (because it only included linkedlist.h).

The naming conventions should be reviewed. You have different capitalizations for your structure tags, which is not good; I stayed with your spellings. I guessed at ll_ and ln_ prefixes for 'linked list' and 'list node' functions — you can use whatever you like, more or less verbosely. The filename suffix p (as in linkedlistp.h) is a terse but moderately common way to indicate that the header is 'private' or 'protected'. You can choose an alternative, probably more verbose, name.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

Short answer, you can't protect variables in a struct, you should consider using classes, or creating methods (functions) to update and read memebers of the struct where you add the logic to prevent access. the docs you give to other devs will contains only the "allowed methods" Keep in mind that anyone can get a pointer to your struct, and since they have the type they can access your struct in any way they want (since anyone can re-define your struct in his/her code).

phoenixstudio
  • 1,776
  • 1
  • 14
  • 19