Is 'private' a C keyword?

2019-02-16 06:16发布

问题:

Are 'private' or 'public' keywords in ANSI C (or any other C for that matter), or were they only added in C++ (and Java, C#, ...)?

回答1:

private is not a C89 or C99 keyword. See C Programming/Reference Tables on Wikibooks*.

Also, C has nothing** to do with Java and C# (and, really, not C++ either). However, the converse is not true -- C++ grew from C, for example.

* Better reference needed!
** Actually, C89 "borrowed" the const and volatile keywords from C++. Likewise, C99 "borrowed" the inline keyword, and also added _Bool and _Complex (like C++'s bool andcomplex, respectively) [citation-needed].



回答2:

Neither are C keywords, but some people do the following:

#define public 
#define private static

Update:

For those who think it is a bad idea to do the above, I would agree. But it does explain why someone might think public or private are C keywords.

For those who think it won't compile in C, try this:

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

#define public
#define private static

private void sayHello(void);

public int main(void) {
    sayHello();

    return (EXIT_SUCCESS);
}

private void sayHello(void) {
   printf("Hello, world\n");
}

For those who think it won't compile in C++, yes the above program will.

Update:

Well actually it is undefined behaviour due to this part of the C++ standard:

A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.

So the example above and below are not required to do anything sane in C++, which is a good thing. My answer still is completely valid for C (until it is proven to be wrong! :-) ).

In the case of a C++ class with private members, you can do something similar (considered an abuse) like this:

main.c:

#include <cstdlib>
#define private public
#include "message.hpp"

int main() {
    Message msg;

    msg.available_method();
    msg.hidden_method();

    return (EXIT_SUCCESS);
}

message.hpp:

#ifndef MESSAGE_H
#define MESSAGE_H

#include <iostream>

class Message {
  private: 
      void hidden_method();

  public: 
      void available_method();
};

inline void Message::hidden_method() {
    std::cout << "this is a private method" << std::endl;
}

inline void Message::available_method() {
    std::cout << "this is a public method" << std::endl;
}

#endif


回答3:

static isn't like private, given that you can't read a static variable even in the constructor of the class (the function which inits members of a struct in C language).

You only can use static variables in the part of the code where they were defined (in a function, a struct, ...).



回答4:

After some thinking i realized that you can just create your own private keyword in c which, like opaque pointers can hide the struct members from the client using an api. So here is a code sample:

api.h

#ifndef API_H
#define API_H

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

#ifdef API_SRC
# define private(x) x
#else
# define private(x)
#endif

struct Api
{
    int thisIsPublic;
    private(int thisPrivate);
};

struct Api *createApi(void);
void foo(struct Api *a);

api.c

#define API_SRC
# include "api.h"
#undef API_SRC

struct Api *createApi(void) {
    return malloc(sizeof(struct Api));
}
void foo(struct Api *a)
{
    printf("%d, %d\n", a->thisIsPublic, a->thisIsPrivate);
    ++a->thisIsPublic;
    ++a->thisIsPrivate;
}

main.c

#include "api.h"
int main(void)
{
    /* works */
    struct Api *a = createApi();
    foo(a);
    printf("%d\n", a->thisIsPublic);
    ++a->thisIsPublic;

    /* doesn't work */
    printf("%d\n", a->thisIsPublic);
    ++a->thisIsPublic;
}

using this concept we can also implement a read-only access specifier:

#ifdef API_SRC
# define readonly
#else
# define readonly const
#endif

// later in the struct this can be used like this:
readonly int x;
// i changed the style of the macro to get it to work with poiters as well:
readonly int * readonly;

There is only one thing to keep in mind, you can use the Api struct on the Stack. At least not client side. I hope this helps someone.



标签: c private