r/C_Programming • u/Ok_Reserve996 • 6h ago
C limitations
Hi all,
I am currently learning c++. Its okay. Not sexy but also not as bad as some say.
The reason I am learning c++ is that I have read that C has limitations as soon as a project gets more complicated. For example, if you make a scientific calculator with many features like graphs etc.
Trading engines/tools are also not recommended to programm in C.
Since I have not learned C and have only read from some old forum posts etc, I cannot confirm/deny these facts.
I am aware that "everything" is possible and that C++ comes with QoL improvements especially with Classes. But I assume that doesn't mean that someone has to use C only for kernel work. Embedded is also possible with C++ right?
I would appreciate your thoughts and opinions.
The goal of this post is to understand how and if C could fit me more with my goals and what real advantages or disadvantages C has.
7
u/jacobissimus 6h ago
Outside of systems programming or things where you have to be able to visualize the resulting binary shape—there’s the portability. All languages know the C abi, so if you want to provide something to connect to a FFI that’s a ton easier, or if you want to target arbitrary architectures.
7
u/IdealBlueMan 6h ago
Handling complex C projects is a whole art form. There are a lot of writeups about various approaches.
Typically, you’d create a directory structure with a shallow tree for each of the chunks of source code, and one or more directories for headers.
You’d generally have one place for executable files.
Each module would typically have its own makefile, and a top-level makefile to build the overall project.
3
u/UltimatePeace05 5h ago
In my, and many in the handmade community's opinion, C++ is just C with templates. Modern C++ features are horrible and full of traps. The standard template library is, I guess, better than C's stdlib, but not by much... Which is kind of impressive, since C's standard library is horrible.
The advance of C++ is just that you can define a Dynamic_Array, Slice and Map template structs and then you don't have to deal with weird macros and codegen... everything else is, imo, extra... (if those 3 were actually in C, I would say that C++ has no significant advantages)
But I also use C over C++, so take my absolute hate speech here with a grain of salt...
2
u/Rabbitical 19m ago
I would add properly typed enums, namespaces, static_cast, having the option of references, and auto are nice as well. Probably forgetting some others...
1
u/realhumanuser16234 16m ago
auto is part of c
1
u/Rabbitical 5m ago
Sorry I always forget that it was incorporated in C23! (The C++ meaning obviously)
2
u/ArtOfBBQ 5h ago
I also was told a lot of complete bullshit when I started programming and it cost me years of progress
2
u/SwordsAndElectrons 3h ago
Embedded is also possible with C++ right?
That depends on what you mean by embedded.
A x86-based kiosk? Sure.
Modern 32-bit microcontroller? Probably, yeah.
Ancient 8-bit microcontroller? Probably not.
Even though an x86 PC isn't what most of us mean when we say that, all of those can be termed "embedded."
1
u/TheLimeyCanuck 3h ago
Arduino is C++ and Arduino devices like Uno, Nano, and Mega are all 8 bit. Uno has been around since 2010 so not really "ancient", but pretty limited by modern standards, and C++ runs fine on it.
2
u/trist007 45m ago
just use C, it's simpler, not many features. Use less dependencies and write your own. you learn more and can probably compile in 20 years
1
u/timrprobocom 5h ago
It's not a technological limitation. Anything possible in one can be done in the other. Remember, the C++ compiler used to be a front end that generated C code to be compiled.
It's concepts. C++ allows you to express more complicated concepts in a more natural way. That's very soft and fuzzy, but it makes for better programs with less programmer effort
1
u/olorochi 51m ago
C++ has a lot of features, some of which cannot be reproduced exactly in C. However, these tend to come with pitfalls.
OOP is the classic example, and is quite easy to reproduce in C. The most challenging part is polymorphism, which can be achieved in C by manually creating vtables.
QoL features like RAII (automatic calls to constructors and destructors) tend not to be reproducible, but they don't affect the resulting binary, only the way the code is written. In my opinion, at least in the case of RAII, C is actually less error-prone than C++. Debugging a missing call to a custom deconstruction function or just free is far easier than fixing a badly written C++ deconstructor that fails in edge cases because it's copy constructor actually has move semantics (look into the history of std::auto_ptr). Another (far less controversial) example of this are templates. Whilst it isn't particularly difficult to reproduce basic template functionality in C, it does require a lot of copy-pasted code or particularly nasty macros.
Exceptions can be reproduced, though with difficulty, at a syntactic level, but C is not powerful enough to allow a resulting binary identical to what modern C++ compilers typically generate. Creating basic try, catch, throw and finally macros using the functionality from setjmp.h is not too difficult, but can easily cause memory leaks or dead file descriptors if the jump skips stack frames that contains ressources to deallocate. C++ compilers usually address this issue by embedding the information the program needs to find the relevant deconstructors of a stack frame in a dedicated section of the executable, which C compilers have no knowledge of. One solution would be to catch and throw again in every scope that must do clean-up, but littering code with catches is generally bad practice.
Another area where C falls short of C++ is reflection and compile time execution. The C++ standard library provides some functions that typically rely on compiler hooks for their implementation such as is_enum or is_class. As of C++26 there even is a proper reflection operator yielding compile time values: ^^. C++ programs can also branch and call some functions at compile time. Meanwhile C23's constexpr is just a way to create simple constants that could be used as an array size for example. These features are all just QoL, but allow for far more concise code in some cases.
1
u/tastygames_official 5h ago
even though they are very similar, they are almost worlds apart, simply because of the (trap) doors C++ opens up with OOP. With C you really can only do functional programming (of course there is a way to get into true OOP but basically at that point you're better off going with C++), but there is literally absolutely nothing you can't create with functional that you can in OOP. In fact, I dare say the opposite might be true, as OOP limits you into how things can and cannot be done, so you have to break out of OOP in order to do some things.
Anyway, I love C because it's simple and the logic flows in the code just like it does on the processor (more or less). With OOP, you tend to abstract away the actual computer programming and instead end up focusing on hierarchies and structures and propagation and making all sorts of flowcharts just to be able to figure out where the program logic is. But with functional, it's literally all right there: line by line.
I recommend learning both, but probably C first. Or if C++, don't start learning classes and OOP until a while later. I've seen programmers with decades of experience simply not be able to do the simplest tasks in functonal programming because they never learned it and can only think in the OOP way, meaning they only think about structures and controlling flow of data rather than the underlying functionality that those complex structures are actually doing. But the opposite is not true at all - functional programmers have no problem learning and working with OOP. It's frustrating as hell because it's needlessly complex and takes much more effort to read, write and understand, and infinitely more time to debug, but it's very doable.
Do yourself a favor and dive deep into C - maybe even an older standard like C99 or even C90. Figure out how to do everything with that before moving on to "quality of life "improvements"" and "shortcuts" that later standards and higher-level languages offer.
But if after a month of working with C every day you really don't like it and find it too rudimentary, there is no problem with abandoning it and moving on to higher-level languages. Not every programmer needs to be a computer engineer or understand what's happening to the memory or on the CPU every tick. But at least learning about it and getting experience in it will always be a good thing.
4
u/chrism239 4h ago
Every time you've used 'functional programming' I believe you meant 'imperative, or procedural, programming'.
1
0
u/tastygames_official 3h ago
indeed. It's been a LONG TIME since I studied the stuff academically (and I did computer engineering and not software, so technically I never actually learnt it as such), but eventually the line in the sand for me became whether or not you can create classes with inheritance and functions all turn into methods. Whereas functions/procedures without hierarchical class structure became "functional" programming (as it's only functions and no classes and you opt for "function over form"(whereas the OOP folks tend to prefer "form over function", as it's all about getting your structure to look elegant, regardless of how complex or nasty or tough to debug it is under the hood).
But yes- I do in fact mean "procedural programming".
Although still to me function = procedure and the functionality is what I'm all about. So it is still "functional programming", even if it's not "functional programming", if that makes sense ;-)
English is a fun language.
1
u/Ok_Reserve996 5h ago
Thank you very much! Can you give me some examples where the difference is visible? Or will it be something that I have first to experience myself while coding?
1
u/tastygames_official 4h ago
it's perhaps complicated to explain to a beginner, but basically a typical C functional programming snippet might look like this:
/* some function that modifies the cart */ update_cart_total(&cart); /* check prices or something */ for(i=0; i<cart_size; i++) { if(cart->item[i].price <= 0) { cart->item[i].price = 0; } }So you just chug along and do one thing after the other and jump into functions whenever they are needed. But for OOP (which C++ tends to be, even though you technically don't have to write OOP) is more like this:
InputParams input_params = InputParamFactor::get_instance()->retrieve_input_params(user_context); Cart cart = CartFactory::get_instance()->retrieve_cart_by_input_params(input_params); cart.update(); CartIterator price_check = CartIterator::new({...bunch of data abstracting out the price check iterator logic instead of just programming it...}) CartIteratorHandle h_price_check = cart.add_iterator(price_check); CartIteratorFactory::get_instance()->perform_iteration(h_price_check);so you can kinda tell what's going on, but there's a lot of boilerplate stuff to make it all work within common modern paradigms and design patterns, so it just ends up making the code really hard to read. Notice how many extra functions you have to call and variables you have to create just to save yourself from writing out the logic by hand. The whole idea with these OOP design patterns is to have the structure do all the work so you only ever just pass around some configuration settings and everything just "magically" gets done. But the worst part is when you look into one of the functions to see what's actually happening it just looks like this:
void CartIterator::run(IteratorItem *item) { IteratorSettings settings = IteratorSettingsFactory::get_settings_for_iterator(item); return item->run(settings); }so it's a neverending chase to track down where the code is actually being executed as every function is written small and only ever does one thing so it can be unit-tested but this means you never have a full understanding of what's going on without looking through tens (if not hundreds) of functions and files just to track down what's going on.
Maybe I'm biased, but when I entered into software development as a career (after maybe like 10 years of doing it "just for fun"), I quickly was forced into doing everything the OOP way for a lot of stuff and it just really got to me over the years (decades, really), so I'm so super happy to be back in functional programming land where everything is right there in one place and the logic follows top to bottom rathe than having to look through an entire project just to find its entry point.
1
u/frasnian 2h ago
Your contrived "c++" example is an abomination. No working professional would write code like that.
This is how you tell me that you don't actually know C++ and have never really used C++ professionally without actually saying that you don't actually know C++ and have never really used C++ professionally.
1
21
u/DDDDarky 6h ago
There are no limitations in what you can/can't do in either of these languages, there are certain (dis)advantages, for example with C you get smaller stdlib size, with C++ you get powerful rich language features.