Learning Rust and C

C++ did not help solve any problems I had. It only added layers of complexity to the solutions.

I have to agree, C++ has presented an ever expanding attack surface to critics and, although I made extensive use of the boost libraries (especially lambda and spirit) in the early 2000's, I've felt little need to adopt any of the features added since C++11 (the auto keword was more than welcome).

Also, a lot of shops I've worked in have ruled out many of the advanced C++ features, even generics beyond the STL. I think one of the key mistakes people make with this language is feeling obliged to use every available feature. Instead, I think the breadth of the language should be seen as an opportunity to tailor a more domain specific subset.

So it's a stretch to suggest that C++ adds nothing useful to C. That's just wrong. Nor is (say) Java a 'better' (more efficient, safer, easier to use) language.

I'm here because I hope to learn and use Rust, because I'm drawn to it's promise of zero cost control over memory management and synchronisation. Truth is, while I know how to do this stuff effectively in C++, I generally avoid threading and prefer event loops. I also use a lot of Python and C, but I think Rust looks like a promising tool for systems programming.

As everyone knows, moving to a new language isn't simply a question of deciding the old one has had it's day. There's a reason that C++ has evolved, rather than being superceded: billions of lines of legacy code. The LLVM toolchain might free things up, but there's still a lot of inertia to overcome.

Also, I'm waiting to see functional languages find greater uptake in commercial development. It seems to take an average of twenty years for the features functional programmers take for granted (exception handling, lambda, continuations, ...) to worm their way into procedural languages. Even the key problem addressed by Rust (data integrity) is obviated by the 'read only' functional model.

Rust's innovation wasn't "data integrity" - it was "data integrity without needing any runtime impact". That's huge.

Also I find the continued C++ hate in here a bit tiresome. It was until Rust the only real contender for a language with the ability to abstract with zero cost: certainly others existed but not with enough of a "killer feature" to get the broad ecosystem support needed to responsibly use a language for anything other than a personal project. Further, C++ has had serious improvements from the committee since 08, and they are only getting more aggressive in their attempts to redesign and replace the flawed bits of the language.

Now that Rust is here, sure, I wouldn't use C++ over it for any new project, but that's more a measure of how good Rust is, not how bad C++ is. For me at least, no language better solves a problem than either Rust or JavaScript (counting Typescript) does, which is quite convenient for development, honestly.

4 Likes

Rust's innovation wasn't "data integrity" - it was "data integrity without needing any runtime impact". That's huge.

I agree, but I thought I'd already noted that with the words 'zero cost'...

Also I find the continued C++ hate in here a bit tiresome.

100%. That's what I was responding to. I didn't mean to suggest that newer features in C++ aren't useful, just that I haven't felt a need for them. Maybe this is just because I don't understand them, but it's sometimes because they don't mesh well with an existing code base.

Also, there are C++ 'features' that have turned out not to be useful, such as exception guarantees in method signatures. As I said, it isn't compulsory to use the entire language set in every project. It's necessary to understand and evaluate these features before they get baked in.

Fair enough, I was responding to this bit :

Which was a fair bit away from talking about Rust being "zero cost". There are plenty of languages that solve data integrity through different mechanisms (Erlang, for example), so this phrasing really minimizes the "killer feature" that is probably the main reason Rust is as popular as it is (though it really helps that it is actually a good language!)

There are plenty of languages that solve data integrity through different mechanisms

Yep, and few offer what Rust does. Erlang, for example, doesn't actually share data, it uses message queues. This is an approach I happen to like, but it comes with some real costs. I see Rust as providing a unique and highly desirable alternative. :slight_smile:

Rust requires putting a lot of things in code that C programmers have to put in documentation or in their heads, which means more work upfront but a lot less work down the line.

Take some C function signature like:

char * do_something(char *a, char *b) { ... }

What do we know about the pointer it returns? Is it something relative to "a" (and shouldn't outlive "a")? Is it relative to "b"? Is it something heap-allocated that needs to be freed later? Can it be NULL? There's no way to know just by looking at it, since C doesn't offer any way to specify that information.

Whereas comparable Rust signatures look like:

fn do_something<'a>(a: &'a str, b: &str) -> &'a str { ... }

fn do_something<'b>(a: &str, b: &'b str) -> &'b str { ... }

fn do_something(a: &str, b: &str) -> String { ... }

fn do_something<'a>(a: &'a str, b: &str) -> Option<&'a str> { ... }

Which are more complicated than the C version, but that extra information tells the compiler about our intent which it can then enforce.

6 Likes

Rust requires putting a lot of things in code that C programmers have to put in documentation or in their heads, which means more work upfront but a lot less work down the line.

That's because C is effectively assembler, in shorthand.

What do we know about the pointer it returns?

It's simple. We know:

  1. it's the address of some memory.
  2. the memory holds sizeof(char) bytes of possibly meaningful data.

Surely that's enough! :laughing:

Ok, it's (slightly) more complicated than that these days, but the point is that C can be read more or less transparently, in terms of operations on an actual machine. That can be very helpful if the machine is something you've just soldered together on a piece of veroboard, but it leaves the handling of a lot of messy details up to the programmer, so it doesn't scale well to, say, implementing a deep learning algorithm.

No. It could be null. Null is not a usable address of anything.

No. Not if it can be null. Or of course it could be the address of many bytes in an array not just 1.

Often it is. :laughing:

It could be null.

Yes yes.. :roll_eyes:

of course it could be the address of many bytes in an array not just 1.

It could... :rofl:

Rust requires putting a lot of things in code that C programmers have to put in documentation or in their heads

Jokes aside, this is an excellent point. The best code is self documenting.

2 Likes

Ups, I guess I may have added some more fuel to that fire. Maybe a little of bit of context on why I expressed my deliberate choice not to use C++ ("I avoided it like the plague"). I work exclusively with low-end embedded systems (think Arduino, not Raspberry Pi). I am not a software engineer, but I did have an "intro to programming" course based on C++ on grad school. The course was very general, and not really tailored for embedded systems. I really struggled with it. In the meantime, I had to write some C code for some embedded projects, and it felt easy and powerful. From that point on, I worked exclusively with C.This was around 2005, C++ was very hyped at the time, but I never really saw the benefit of it. And this is not to say that C++ is a bad/useless language (I understand it is great for GUI, and game development), it is just that to me and in my line of work, that added complexity brings more troubles than benefits (my personal opinion). Many embedded compilers do not support C++, and the ones who do, only support a small subset of C++ features. The popular Arduino is based on very simple C++, i.e. C with classes. I can work with that!

This brings me back to Rust. At the beginning, Rust felt similarly complex to C++ (and maybe it is), and I struggled a lot. But, as other have mentioned, the promise of memory-safe embedded software (Rust's killer feature) is what made me try harder. I have no regrets... :slight_smile: Cheers

1 Like

The C++ (and C) compiler for Arduino (and AVR in general) is GCC. It fully supports whatever C++ features GCC has anyway (that depends on the front-end, not the back-end of the compiler). Of course the standard library is harder to implement fully because of the lack of virtual memory/allocation, but the language itself is not any simpler than "C++ for not-Arduino" is. (To the contrary, avr-gcc actually adds some language extensions required by the memory model of the device, such as the __attribute__((progmem)) attribute.)

1 Like

As far as I know that is true.

However the Arduino creators did some very smart things. Perhaps chief of these is never referring to the language their system uses as C++. They would talk of "Processing" or whatever it is called. A user gets the Arduino IDE, which is dead simple and hides all the grubby details of building code and programming the chip. A big thing was providing copious libraries documentation on their "Processing" environment which studiously omitted any mention of C++ or almost all C++ features, except those features that can be leveraged to make programs look as simple as possible.

The end result is that the typical Arduino user has never heard of C++, does not know they are using C++, they have a happy time using a very simple subset of the language with nothing overly complex or arcane to scare them off.

1 Like

…along with a ridiculously unacceptable level of runtime and binary size overhead for simple tasks like setting a pin or talking to USART. It may be programmer-wise convenient for those who don't know what they are doing, but for the rest, it's not a very "smart" move. It ends up doing more harm than good.

The thing is, the vast majority of people using Arduinos are going to be non-programmers trying to just hack things together or software engineers making a quick'n'dirty prototype. For that audience it makes sense to optimise for convenience at the cost of inefficiency.

You'll find that most people who care about runtime and binary overhead naturally switch to a platform that gives them more fine-grained control like an STM32 and its HAL. They're the sorts of people that will want to design things properly with low-cost abstractions and good architecture because they are often building a large number of units or will need to maintain the codebase over time.

To give some counter-evidence: I never needed to deploy a large number of embedde devices in a professional setting, but I found the Arduino libraries basically unusable even for the small projects I made (and ended up writing my own high-level HAL for AVR).

The reason for that is that the runtime overhead was so big that it was for example impossible to implement interfacing with an external chip that required irregular and aperiodic pulse trains. So one usually goes ahead and implements this sort of thing with synchronous delays, but that simply failed because the Arduino HAL used virtual methods (!) in some of the code implementing I/O bit banging, and the latency of the virtual call was higher than the delays between bits.

The AVR would be a perfectly fine platform even for more serious work. The raw avr-libc routines and macros provide the potential of writing very low-overhead code, but they are a bit too low-level. It wouldn't have been impossible to design and implement the Arduino layer in a way that doesn't suck, because again, I was able to create a parallel implementation with identical functionality which incurred much less overhead. I think the problem is not that they are trying to cater to non-professionals; I just genuinely think that the code quality is simply very low (and unsalvageable at this point without serious breakage).

3 Likes

This would have been effectively c++98, the first standard version then (there's an 03, but it's pretty minor) - the C++11 and up updates have been pretty wild and really cleaned up and extended the language in lots of ways: it's still c++, but it's really quite fresh feeling. A lot of Rust's design is pulling from the work done in these updates, with the benefit of a clean slate.

It's also important to note that that was the era of peak terrible C++ guidance: make everything a deep class heirachy, raw new and delete, nonsense operator overloading, and nobody know how to do RAII properly yet. And multithreading was effectively impossible to do correctly, needing deep research into the guarantees provided by all of the compiler, operating system and architecture. Libraries like Boost did a lot of discovering what was a good idea (though perhaps largely by finding everything that was a bad idea first! :smile:) Nowadays we have a lot better understanding of how to not screw up C++, and the language has shifted to bake that knowledge in where it can. And you can even read a directory!

(Interestingly, JavaScript has had a very similar trajectory: being bad but necessary until an industry committee formed and totally turned the language around with some really clever design work)

3 Likes

This has been roughly my experience with C++: I learned it in the early 2000's and came to the conclusion that the vast majority of its improvements were actually a downgrade compared to C. In the intervening 20 years, C++ has changed enough that it's effectively a different language than it was when I was originally exposed to it. I can easily believe that C++new has managed to fix most of the problems that I experienced with C++old, but I also haven't found a compelling reason to invest the effort to learn C++new. That's not to say that nobody should learn or use C++new, of course— There's lots of useful software written in it that has to be maintained if nothing else.

2 Likes

@Michaelin007, if you haven't seen this yet, I highly recommend Brad Traversy's YouTube Tutorial.

When I started Rust, that video was what I needed to get going quickly. And you can download the related source files here.

As someone who has long been a big fan of C, I recommend starting with Rust and skipping all of the pain, only to realize that C isn't as easy (or safe) as it appears.

On the other hand, if you really want to learn C, go for it. It's still not a bad thing to have on your résumé.

3 Likes

Thanks , I will check it out. I'm a bit comfortable with the basic.

Have really learn a lot from the thread. There are lot of experience developers in this forum which make it a good place to learn and also make the journey easier.

I also intends to rewrite some of the codes in learn c the hard in rust. Anytime I'm stuck, I will always ask here :slight_smile: Thanks to this awesome group. People here are so good.

Thanks a lot

1 Like