News for hackers. Stuff that matters.
Re:The C Programming Language: Myths and Reality (1) by Joker_vD on Monday July 17, 2023 @10:10AM (#36758468)
> It does not work on a field, but on the whole struct.

    struct PrivateFieldsOfMyShinyClass;

    struct MyShinyClass {
        int somePublicData;
        double morePublicData;
        struct PrivateFieldsOfMyShinyClass *p;
    };
> malloc isn't possible, but neither are copies by value, sizeof() breaks

Those are implementation details which are deliberately being hidden.

> Completely incompatible with inlining code.

They are as incompatible with code inlining as public/private modifiers in C++ are. That is, LTO is your best friend here. Also, have you ever tried to maintain binary compatibility with several versions of a third-party C++ library that keeps adding/removing private fields to/from its classes?

Re:The C Programming Language: Myths and Reality (1) by gjulianm on Monday July 17, 2023 @10:33AM (#36758719)
> Those are implementation details which are deliberately being hidden.

I know they're being hidden deliberately, but in C++ "private" doesn't break malloc (new), copies by value or sizeof. Or stack allocation, to add to the list.

> They are as incompatible with code inlining as public/private modifiers in C++ are. That is, LTO is your best friend here.

public/private aren't incompatible with inlining in C++. That is, you can call class functions that access private members and the compiler can inline those functions. Also, LTO is not always enabled by default, and doesn't always inline the things you want it to inline.

> Also, have you ever tried to maintain binary compatibility with several versions of a third-party C++ library that keeps adding/removing private fields to/from its classes?

I mentioned binary compatibility as one of the reasons one might want to do this. However, if you have a third party that doesn't care about API compatibility I doubt struct fields are the only thing they're going to change constantly.

Re:The C Programming Language: Myths and Reality (1) by skribanto on Monday July 17, 2023 @02:51PM (#36762381)
Maybe have your public fields defined as a second struct, and then you can cast the pointer to your struct to the concrete struct that has all the public fields. This has the restriction that all public fields must be at the start, and you must make sure to maintain the same order between the two structs.

At this point though, I think I honestly would prefer setters/getters.

    struct MyClassPublic {
        int x;
        int y;
        ...
    }

    /* using it */
    MyClass *myclass = myclass_create();
    ((MyClassPublic *)myclass)->x = 5;
Re:The C Programming Language: Myths and Reality (1) by jstimpfle on Monday July 17, 2023 @10:17AM (#36758525)
Hiding members in this way is only possible with pointer indirection, which isn't satisfying.

However, having only a boolean private/public access state isn't generally satisfying either. It often leads to violation of the principle of separation of concerns when all the functions (methods) acting on certain "private" fields need to live in the same class.

In simple classes, like std::vector, it's possible to get away with private. But in many cases that are more complex than that, it seems to me that the best approach is still to expose the data and to be just very clear about the exact purpose of each member.

Re:The C Programming Language: Myths and Reality (1) by dfawcus on Monday July 17, 2023 @03:09PM (#36762600)

    struct public_stuff {
        ...
    }

    struct private_stuff {
        struct public_stuff public;
        ...
    }

    struct public_stuff *make_public(/* ... */) {
        struct private *prv = malloc(sizeof *prv);
        /* ... */
        return &prv->public;
    }
Then when passed in to functions, cast the passed in struct pointer to the private one.

The public struct doesn't even have to be at the start if one make appropriate use of offsetof and ensuring valid alignment.

Nothing new under the sun...