5 ms·
> C has a type system, but the developers are ignoring it, preferring to move stuff around as void *. Obviously, it shouldn’t be necessary to do that, and this
by smcameron 4y ago
> C has a type system, but the developers are ignoring it, preferring to move stuff around as void *. Obviously, it shouldn’t be necessary to do that, and this was one of the things I wanted to fix by moving the code into a C++ compiler.
> This is a case of one function infecting the entire code base. In this case, a function that is often invoked, the xmalloc family, a wrapper over malloc-like functions that return pointers to void.
This makes no sense to me. In C, you can assign a void pointer to any typed pointer, no casting required, i.e.:
struct foo *f = malloc(sizeof(*f));
The answer here isn't to rewrite it all in C++, but to learn C in the first place.
- void_ptr__ 4y agoThey may be referring to xmalloc(3). What you said is true however they are transitioning to a C++ compiler so your complaint is off-base.
- masklinn 4y ago> however they are transitioning to a C++ compiler OP says they want to transition to a C++ compiler but it's not clear why, the very first issue is not actually one. As GP notes, you don't need to cast out of malloc and you need a macro even less.
- quietbritishjim 4y agoWhen the article says that implicit conversations from void* "shouldn’t be necessary" they seem to mean they feel that, philosophically, it ought not to be necessary. Certainly it doesn't protect against obvious compile time mistakes, which ought to be the point of a type system: /* Compiles in C */ int* x = malloc((sizeof)short) // Does not compile in C++ int* x = new short
- ginko 4y agoI mean sure, but that seems like a minor thing compared to the codebase passing around void*'s left and right. OP could have tackled that first while sticking with C. I've had a brief look over the goaccess source code. It's 37kloc of pretty average looking C. If you think that's even close to the most complicated software projects written in C then I don't know what to tell you.
- bornfreddy 4y agoLink if anyone else is curious (and lazy) : https://github.com/allinurl/goaccess https://github.com/allinurl/goaccess EDIT: looked at the code... I don't see void* being passed around, data types are used, no excessive #ifdefs, it looks like a pretty clean C app to be honest. Maybe the problem is that OP is used to C++? (as the advice to use a special struct for strings would indicate) Either way, goaccess project looks awesome.
- mananaysiempre 4y agoWhat are the typing-related issues xmalloc has that plain malloc doesn’t? As far as I can see, they’re equivalent in that respect.
- bitwize 4y agoNo. For a project like this you absolutely want the stronger type guarantees and abstractions that C++ gives you. Were it me, I'd RIIR, but C++ that uses the type system and const-correctness in the proper way is an improvement.
- WalterBright 4y agoConst-correctness doesn't actually work in C++. It's more of a documentation aid. (It doesn't work because it can be cast away. It's also not transitive, so is ineffective with generic template code.) D code won't allow const to be cast away (unless in system code), and is transitive. Sometimes people complain that this is too harsh, but it's reliable and effective.
- maccard 4y agoI can't believe I'm about to try and correct you of all people on this but you can't just const_cast away[0]. The actual problem is that you have no guarantee that what you're being told is const is actually const. If you have a const ref to an object, that doesn't mean it's actually initialised as const, for example. [0] well of course technically you can, but casting a CV qualifier away and modifying it is UB.
- WalterBright 4y agoYes, you are correct, it is UB. Try this code: void foo(const int * const p) { *(int*)p = 3; // UB? So sue me! } It compiles with g++ and clang++ with no warnings or errors. gcc and clang, too. Sure, it's UB, but the compiler won't even warn you. I.e. it serves no purpose, other than documentation. Let's try it in D: @safe void foo(const int *p) { *cast(int*)p = 3; } Error: cast from const(int*) to int* not allowed in safe code
- maccard 4y agoI think we're in agreement here, but speaking past each other! Your snippet isn't actually UB though, it's perfectly fine. See [0] > I.e. it serves no purpose, other than documentation Yeah, agreed. [0] https://gcc.godbolt.org/z/v4qYME8fP https://gcc.godbolt.org/z/v4qYME8fP
- deleted 4y ago[deleted]
- shrimp_emoji 4y agoOne problem is that, when you cast to `void*`, you discard size information. I have a `double*`, I know the size of the object behind that pointer is `sizeof(double)`. If I have a `void*`, and nothing else, all bets are off.
- masklinn 4y agoOP is saying that you don't need an explicit cast to cast from a void* (which is what malloc returns).
- shrimp_emoji 4y agoIn that case, I guess >C has a type system, but the developers are ignoring it, preferring to move stuff around as void *. is alleging that C programmers insist on literally keeping their allocated variables behind `void*`s. That's too weird to me. :p Because, yeah, you don't need an explicit cast from a `void*` returned from a `malloc`, and I assume everyone tacitly assigns that `void*` to a `Foo*` immediately. The only case where you're converting stuff to `void*`s is when passing/taking it to/from "generic" APIs, where it could be any type. (Hence "move stuff around".) I thought OP was alleging there's no problems with this practice, although that interpretation of mine doesn't make sense from what they said in retrospect.
- wizofaus 4y ago"Some non-zero multiple of sizeof(double)", surely?
- mananaysiempre 4y agos/non-zero // double x[1], *p; p = x + 1; /* legal though *p wouldn’t be */
- wizofaus 4y agoSurely in that case x[0] is the object "behind" the pointer (assuming adding 1 puts you ahead!). But using the orginally intended meaning of "behind" here, logically there is no object at all...
- Gibbon1 4y ago> move stuff around as void * People do that because they don't understand how to define and use opaque pointers. Also if someone would put the C standards committee on an ice flow and replace them with people willing to add first class types and tagged unions to C that would be nice.
- gsinclair 4y agoice floe*
- avinassh 4y ago> People do that because they don't understand how to define and use opaque pointers. what are opaque pointers?
- masklinn 4y agoPointers to a well-defined type, but one which does not reveal the underlying datatype so a user is unable to interact with the actual data without going through the library’s exposed API (or at least strongly disincentivised from doing it). IIRC the normal way to do that in C is to use an incomplete type, aka just have a struct foo; In the header file and define the actual struct contents in the implementation file.
- Gibbon1 4y agoYou can create a pointer with a type but no storage definition. // foo_t is opaque typedef struct foo_s foo_t; // function defined taking an opaque pointer int Baz(foo_t *f); // actual definition typedef struct foo_s { int bar; } foo_t; // function def int Baz(foo_t *f) { return f->bar; }