5 ms·
I write mostly like I would in C, but use C++ features as needed. It ends up looking similar to Rust if you squint. All these "I write games in C" people compla
by torlok 8mo ago
I write mostly like I would in C, but use C++ features as needed. It ends up looking similar to Rust if you squint. All these "I write games in C" people complain about C++ features, and then end up reimplementing virtual interfaces manually with struct headers or massive switch statements, just to feel better about themselves. Writing games in C is not harder, you just have to implement modern language features by hand.
Complaining about a language having features you don't want is silly. C++ doesn't take longer to compile if you don't abuse templates.
- pansa2 8mo agoYeah, you could argue that choosing C is just choosing a particular subset of C++. The main difference from choosing a different subset, e.g. “Google C++” (i.e. writing C++ according to the Google style guide), is that the compiler enforces that you stick to the subset.
- ninkendo 8mo agoC's string handling is so abominably terrible that sometimes all people really need is "C with std::string". Oh, and smart pointers too. And hash maps. Vectors too while we're at it. I think that's it.
- teo_zero 8mo agoI agree on the former two (std::string and smart pointers) because they can't be nicely implemented without some help from the language itself. The latter two (hash maps and vectors), though, are just compound data types that can be built on top of standard C. All it would need is to agree on a new common library, more modern than the one designed in the 70s.
- uecker 8mo agowhy not std::string?
- direwolf20 8mo agoIt's a class, so it doesn't work in C.
- uecker 8mo agoSure, but you can have a similar string abstraction in C. What would you miss? The overloaded operators?
- direwolf20 8mo agoAutomatic memory accounting — construct/copy/destruct. You can't abstract these in C. You always have to call i_copied_the_string(&string) after copying the string and you always have to call the_string_is_out_of_scope_now(&string) just before it goes out of scope
- uecker 8mo agoThis seems orthogonal to std::string. People who pick C do not want automatic memory management, but might want better strings.
- direwolf20 8mo agoAutomatic memory management is literally what makes them better
- uecker 8mo agoFor many string operations such as appending, inserting, overwriting etc. the memory management can be made automatic as well in C, and I think this is the main advantage. Just automatic free at scope end does not work (without extensions).
- direwolf20 8mo agoYou can make strings (or bignums or matrices) more convenient than the C default but you can never make them as convenient as ints, while in C++ you can.
- ninkendo 8mo agoI think a vec is important for the same reason a string is… because being able to properly get the length, and standardized ways to push/pop from them that don’t require manual bounds checking and calls to realloc. Hash maps are mostly only important because everyone ought to standardize on a way of hashing keys. But I suppose they can both be “bring your own”… to me it’s more that these types are so fundamental and so “table stakes” that having one base implementation of them guaranteed by the language’s standard lib is important.
- WalterBright 8mo agoWhen I developed D, a major priority was string handling. I was inspired by Basic, which had very straightforward, natural strings. The goal was to be as good as Basic strings. And it wasn't hard to achieve. The idea was to use length delimited strings rather than 0 terminated. This meant that slices of strings being strings is a superpower. No more did one have to constantly allocate memory for a slice, and then keep track of that memory. Length-delimited also super speeded string manipulation. One no longer had to scan a string to find its length. This is a big deal for memory caching. Static strings are length delimited too, but also have a 0 at the end, which makes it easy to pass string literals to C functions like printf. And, of course, you can append a 0 to a string anytime.
- jfaulken 8mo agoJust want to off-topic-nerd-out for a second and thank you for Empire.
- WalterBright 8mo agoYou're welcome! One of the fun things about Empire is one isn't out to save humanity, but to conquer! Hahahaha. BTW, one of my friends is using ClodCode to generate an Empire clone by feeding it the manual. Lots of fun!
- 9rx 8mo agoAdd concurrency and you more or less came up with same list C's own creator came up when he started working on a new language.
- saidinesh5 8mo agoAnd constructors and destructors to be able to use those vectors and hash maps properly without worrying about memory leaks. And const references. And lambdas.
- pjmlp 8mo agoYeah, WG14 has had enough time to provide safer alternatives for string and arrays in C, but that isn't a priority, apparently.
- tialaramex 8mo agoThe C++ std::string is both very complicated mechanically and underspecified, which is why Raymond Chen's article about std::string has to explain three different types (one for each of the three popular C++ stdlib implementations) and still got some details wrong resulting in a cycle of corrections. So that wouldn't really fit C very well and I'd suggest that Rust's String, which is essentially just Vec<u8> plus a promise that this is a UTF-8 encoded string, is closer.
- klaussilveira 8mo agohttps://bkaradzic.github.io/posts/orthodoxc++/ https://bkaradzic.github.io/posts/orthodoxc++/
- pantalaimon 8mo agoC is not a subset of C++, there are some subtle things you can do in C that are not valid C++
- uecker 8mo agoSome subtle and some not so subtle.
- pjmlp 8mo agoIt is when compared with C89, also the ISO C++ requires inclusion of ISO C standard library. The differences are the usual that occur with guest languages, in this case the origin being UNIX and C at Bell Labs, eventually each platform goes its own merry way and compatibility slowly falls apart with newer versions. In regards to C89 the main differences are struct and unions naming rules, () means void instead of anything goes, ?: precedent rules, implicit casts scenarios are reduced like from void pointers.
- saidinesh5 8mo agoLinters etc... Validates the subset you're choosing to use for your project too.
- randomtoast 8mo agoI’ve seen this play out a lot. People say they “write games in C” and then quietly rebuild half of C++ anyway with vtables in structs or giant switch statements, just without the compiler helping. That’s fine if it makes you happier, but it’s not obviously simpler or safer. Also, C++ compile times are mostly a self-inflicted wound via templates and metaprogramming, not some inherent tax you pay for having virtual functions.
- direwolf20 8mo agoIt's important that you do these things yourself before you utilise the compiler to do them for you, so you have real understanding.
- deleted 8mo ago[deleted]
- sandpaper26 8mo agoThis reads like an LLM generated response that simply restates the comment it's replying to
- randomtoast 8mo agoHeck the LLM accusations get a bit out of hand lately here on HN. I could delve into it now ... but I want to safe our time.
- mjburgess 8mo agoA switch statement is how you do ad-hoc polymorphism in C -- i dont thinks an own against C developers to point that out. If they wanted to adopt the C++ style that immediately requires the entire machinery of OOP, which is an incredibly heavy price to avoid a few switch statements in the tiny number of places ad-hoc poly is actually needed
- whizzter 8mo agoYou don't usually do C++ subsets if you want the full shebang. I have a "mini-std" headerfile that's about 500 LoC implementing lightweight variants of std::vector, std::function, a stack-local std::function (unsafe as hell and useful as hell to avoid allocations), a shared-ptr, qsort and some other nifty stuff. That does a lot of things, but even then I use other patterns that brings a lot of bang for the buck without having to go full C (hint: the stack-local function equivalent gets a lot of mileage).
- pron 8mo ago> Complaining about a language having features you don't want is silly. It might be silly if you're working on your own. Software that delivers a lot of value is usually developed and evolved not only by team, but by a team with changing members and changing leadership over the project's lifetime. The features used will be the union of all features used over the years, and while it's easy for team leads to allow the use of more features than their predecessors, it's quite hard to reduce them. Also, you may be forced to use language features you don't want if they're used by libraries whose functionality you do want. For example, when doing low-level programming, I don't like implicit calls that I can't clearly see on the page (e.g. destructors or overloaded operators). But if libraries I want use them, then I'll have those implicit calls. But if the language doesn't have those features, libraries obviously won't use them.
- karamanolev 8mo ago> It might be silly if you're working on your own. That's exactly the case when it's easiest. If you don't need a feature, just don't use it and case closed. With a team it's harder - you have to force/enforce others not to use a given feature. > if they're used by libraries whose functionality you do want If you're using C++ you can just use the C library you would've used otherwise, no?
- adastra22 8mo agoThere are linters to do that enforcement automatically.
- Yokohiii 8mo ago> Also, you may be forced to use language features you don't This is quite important and often overlooked. An annoying fallacy is that people think some features are optional, but once they get heavily used, they aren't anymore. Often they quickly become an requirement and if you don't follow suit, your code is legacy or you are an idiot. But well, I guess I create legacy code upfront and the cargo cultists create modern code that turns into legacy next day.
- etrvic 8mo agoI feel like, for me, it’s that I am more familiar with writing in C and switching to C++ seems rather difficult. So, sure I am reimplementing features that already exist in anoter language, it just so happens in this case is C++. Why not use python if you want to avoid reimplementing the wheel as much as possible. And sure python is not suited for game development but I just wanted to make a point with it. I think in the end ising a language you are most familiar with results in the most amount of enjoyable coding.
- cogman10 8mo agoFor a solo dev, it's not difficult. C++ is nearly a superset of C. You don't have to adopt all of C++ to start using it and to get immediate benefits from it (for example, unique_ptr, shared_ptr, and vector would all be things that I think any C dev would really appreciate). A reason I can think of to not move to C++ is that it is a vast language and, if you are working on a team, it can be easy for team members ultimately forcing the whole team to become an expert in C++ simply because they all will be familiar with a different set of C++ features. But for a solo dev? No reason not to use it, IMO. It's got a much nicer standard library with a rich set of datastructures that just make it easier to write correct code even if you keep a C style for everything.
- pjmlp 8mo agoI learnt C++ on Turbo C++ 1.0 for MS-DOS as teenager, after doing C with Turbo C 2.0. Being on Borland ecosystem that was followed by several years of Object Pascal (I was already using TP at the time), and C++. Never got the point of why to keep using C, other than external constraints like school assignments, jobs requirements or lack of compilers.
- krapp 8mo ago>Writing games in C is not harder, you just have to implement modern language features by hand. I feel like if you need to implement modern language features, you shouldn't be using C. The entire point of C is to not be modern.
- tomcam 8mo ago> just to feel better about themselves. Mindread much?
- whizzter 8mo agoExactly, not even do you need to religiously need stick to your subset, separate modules can be using supetsets that import useful libraries and if they're used for code that is seldomly changed (such as model importers) then the longer compile time will only matter for rebuilds and not quick tests.
- petters 8mo ago> C++ doesn't take longer to compile if you don't abuse templates. Surprisingly, this is not true. I've written a C++ file only to realize at the end that I did not use any C++ features. Renaming the file to .c halved the compilation time.
- levodelellis 8mo agoI don't believe you, I measured compile times in c compilers and my own. If you provide more information I'd be more likely to believe you
- petters 8mo agoThat's fair. I'm unable to provide more information though so we'll have to disagree.
- flohofwoe 8mo agoOn some compiler toolchains (IIRC MSVC was the main offender) you get a lot more code pulled into your source file when including a C stdlib header (like <stdio.h>) in C++ mode versus C mode. Basically a couple hundred lines in C mode versus thousands of lines in C++ mode.
- levodelellis 8mo ago[flagged]
- jsheard 8mo agoI agree it shouldn't really matter if there's no C++ features in play, but I suppose third party headers could bite you if they use #ifdef __cplusplus to guard optional C++ extensions on top of their basic C interface. In that case the compiler could be dealing with dramatically more complex code when you build in C++ mode.
- uecker 8mo agoMaybe it is similar for the same compiler (but one should check, I suspect C could still be faster), but then there are much more C compilers. For example, TCC is a lot faster than GCC.
- levodelellis 8mo agoI measured once and to my surprise templates aren't (directly) the reason for long compile times. It's function bodies in headers, and obviously templates are in headers and they call other templated functions/classes which explodes code generation and time. But if it's only a few lines and doesn't call other templated functions it's likely fine. I wrote about it here https://bolinlang.com/wheres-my-compile-time https://bolinlang.com/wheres-my-compile-time After writing that, I wrote my own standard library (it has data structs like vector, hashmap and sets; slices, strings, rng, print, some io functions, and more) which uses a lot of templates, and it compiles in <200ms on both clang and gcc. Many standard library headers take much longer to compile than that. It's not a terrible idea to have your own standard lib if you need quick compile times.
- direwolf20 8mo agoYour website seems to be blocking Tor
- levodelellis 8mo agoOh? I use a boring old $5 VPS (using nginx for https). There's no cloudflare or anything else involved. I wonder why that's happening. I may look into that this week
- direwolf20 8mo agoIt could also just be down. I didn't try outside of Tor
- rustyhancock 8mo agoAnother option can be if you have a core set of headers your project will use (and is stable) just precompiling them.
- HoldOnAMinute 8mo agoIt's possible to use only a subset of the language. You could write a Java program without classes if you really wanted to. Just put the whole thing in main(). A lot of smart people pick and choose what they want from the language, just like religion, they keep the good parts and discard the bad.
- direwolf20 8mo agomain is also in a class in Java. Even with the recent extension where it looks like it isn't, the compiler adds one for you.
- bobajeff 8mo agoI remember the creator of Kaiju engine stating something about C++ compilers producing slower code with C-style C++.
- direwolf20 8mo agoThat's probably to do with exceptions — possibly the only thing that pervades C++ code even if you don't use it. The compiler has to write code so an exception at any point leaves the stack in a sensible way, etc. Try -fno-exceptions (and -fno-rtti might save some memory while you're at it) Regrettably not every C++ feature is free if you don't use it. But there aren't many that aren't.
- wasmperson 8mo agoFor every person who says on the internet that you can just use a C++ subset, there's another who insists that C is the bad C++ subset. So compiling C code with a C++ compiler promotes your code from "good C code" to "bad C++ code" (most C code isn't "exception safe," for example). It's arguably irrational to evaluate a language based on this, but you can think of "this code could be better" as a sort of mild distraction. C++ is chock full of this kind of distraction.
- feelamee 8mo agoOf course people do" virtual functions" in C, but I think this is not an argument despite C. I noticed that making virtual in C++ is sooo easy that people start abusing it. This making reading/understanding/debugging code much harder (especially if they mess this up with templates). And here C is a way - it allow but complicates "virtual". So, you will think twice before using it
- card_zero 8mo agoC++ reimplements a lot of the things we do in C with function pointers, while hiding what's actually happening behind topheavy syntax that implies a 1990s object oriented paradigm that's dead now.
- direwolf20 8mo agoContrary to popular belief C++ isn't really object–oriented. I mean, you can write object–oriented code, but the language doesn't make assumptions about what goes into a class. It's really just a struct with associated functions.
- Yokohiii 8mo agoThat's an odd opinion about a language with a lot of class related features. I can only assume you have a very strong definition of OOP.
- direwolf20 8mo agoOOP doesn't mean that your language has a "class" keyword, nor dot notation for calling functions.
- afiori 8mo agoI enjoyed the pragmatic historical definition of OOP given in https://www.youtube.com/watch?v=wo84LFzx5nI https://www.youtube.com/watch?v=wo84LFzx5nI where essential it can be seen as subtype polymorphism
- flohofwoe 8mo ago> It's really just a struct with associated functions. If that were actually true C++ would be a lot easier to accept as a 'C successor'. Instead you have the implicit this-pointer, complicated rules for which constructor or operator overload is actually called, a hidden vtable pointer (not to mention multiple inheritance), then you have public/private/protected, override vs final, const methods (which wouldn't be needed as a separate syntax feature if the this arg wouldn't be implicit) etc etc etc... that a lot of OOP-baggage which a lot of C++ coders probably don't even notice anymore. A plain C struct with function pointers does indeed make a lot more sense than all the OOP-ism that C++ hides from you ;)
- tialaramex 8mo ago> then end up reimplementing virtual interfaces manually C++ dynamic dispatch (your "virtual interfaces") is achieved by welding a vtable onto every type and providing a pointer to that vtable for instances of the type. If in 90% of your code you deal with specific types like Goose or Swan or Duck or Seagull, and only 10% needs to work with the broad Bird category well, too bad, every Goose, Swan, Duck and Seagull carries around that vtable pointer even if it goes nowhere near that 10% of the system. This way your Bird code "just works" in C++. That's not the only way to crack this nut. Idiomatic Rust approach uses vtables only in the Bird code, elsewhere they don't exist, and thus don't take up space in a Duck or whatever that's always a Duck, but in exchange now you're spending more time thinking, because by default there aren't any vtables and so dynamic dispatch isn't possible at all. So while that C programmer has to implement features by hand, they are at least able to specifically implement the feature they wanted, not whatever was easiest for Bjarne Stroustrup last century.
- agentultra 8mo agoC++ nudges you to think in terms of single elements. Operator overloading, ctors/dtors, references, etc. you pay that cost all over the place. C programs tend to nudge you into thinking in terms of arrays of data. For game development you generally want to think this way. The cost of vtables and all the cache misses doesn’t have to be paid. A game has to stream bytes. Many things at once. Rarely single elements at a time.
- pjmlp 8mo agoOnly if devs lack the skills to understand what to actually use. There is this anti-C++ bias that keeps forgetting that using C++ doesn't mean use every feature. Just like many keep using C as if C89 was latest, and never adopt anything added in the last 30 years.
- avadodin 8mo agoWhat this comment looks like to a C programmer: >> C89 > agree :D
- Suppafly 8mo ago>C is not harder, you just have to implement modern language features by hand That's definitely harder.
- lelanthran 8mo ago> Complaining about a language having features you don't want is silly. If your criteria for a good language is "how many features does it have", then sure, C++ wins. OTOH, if you criteria is "How many footguns does the language have" then C++ loses to almost every other mainstream language, which includes C. Sometimes the lack of footguns is a plus.
- jamienicol 8mo agoSurely your criteria should be some combination of the two (plus other factors). C may have fewer footguns than C++, but it still has many, whilst also lacking many useful features
- lelanthran 8mo ago> Surely your criteria should be some combination of the two (plus other factors). Sure, but the weighting would be different for different people. > C may have fewer footguns than C++, but it still has many, whilst also lacking many useful features We are not talking "2 fewer footguns", or "5 fewer footguns"; we are talking "dozens fewer footguns". When I need a language with more features than C, I don't choose C++, because the choice is not "Use C for simplicity, and use C++ to trade simplicity off against features", it's usually "Use C for simplicity, and use Java/C#/Go/Rust for features".
- flohofwoe 8mo ago> C++ doesn't take longer to compile if you don't abuse templates. It actually does though, unless you also drop C++ stdlib usage completely (have you looked at how many lines of code just <vector> alone pulls into each source file? - it's upward of 20kloc and growing with each new C++ version). And at that point you get into discussions with various C++ camps about why you don't use the C++ stdlib and instead prefer to reinvent the wheel (and this friction with other C++ coders is the main problem of carving out your own subset - it works ok in complete isolation, but software development work hardly happens in splendid isolation and even then you'd might to want to use C++ libraries written by other people from time to time...) And once you've been dragged into such C++-subset-discussion month after month, year after year, at that point it is much less exhausting to just write plain C. And the C community (if it can be called that) seems to be much less concerned about coding style dogma and generally a nicer bunch to interact with. FWIW, I switched around 2017 and each time I have to interact with a C++ library for lack of alternatives it's usually not a pleasant experience (with the notable exception of Dear ImGui - but even there I started to prefer the C bindings so that I don't need to strictly separate the UI code from the rest of the code base, which sometimes makes sense, but often not, especially with an immediate mode UI framework).
- patrick451 8mo agoAt least you can read the switch statement. One of the worst features of c++ is all of the code that gets generated for you automatically.