🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Has C# replaced C++?

Started by
70 comments, last by Prototype 4 years, 10 months ago
1 hour ago, TheIndieteurGuy said:

The point I was trying to make is that C#, as it is designed, requires .NET framework to run while C++ doesn't require any of that.

C and C++ need a runtime library to communicate with the host environment as well. There isn't really such a thing as 'library-free' programming on a modern OS.



 

Advertisement

Which brings me to a possibly naive question of a hobbyist.

Is there really such a thing as a dedicated "runtime environment" for C or C++ ? I mean, there is the OS with its functionality for memory and io stuff, and driver routines that one can call. Also some routines to care for the stack (are these built into the executable program when linking ?) and other statically or dynamically linked libraries the program depends on.

Everything else like JIT compilation or byte code interpretation, GC, ... that would be needed for C# or Java, is not intrinsically part of the languages C or C++. Does this theoretically mean that C# or Java programs are more portable between platforms/architectures (on the cost of execution speed), while a C or C++ program must be specifically compiled (but can therefore also be specifically optimised) ? If yes, how big is the advantage of gaining portability in real life, when a (possibly huge, buggy and rights protected) runtime environment must be ported and maintained for any of these platforms/architectures.

But i don't want to take up any cudgel here. Apparently one can program in any language, and C# and Java may be more likely to attract new people into programming because they are rumoured being easier to learn. I mainly switched to C++ when i realized monodevelop won't run on my Linux ...

 

Edit:

I see there were/are attempts to slide in an object code layer for C++ to achieve more portability, but i don't feel entitled to comment it.

https://isocpp.org/files/papers/n4028.pdf

 

 

This reminds me of when my roommate once told me that we'll have nearly realistic graphics that were comparable to the ray tracing of the late 90's early 2000's all in real time. I was adamant that there was no way, figuring the advances in ray tracing would be too fast to catch up to.  Guess what?  I was wrong. Very wrong. And I'm proven even more wrong with each quarter that passes.

If you told me JavaScript would be dominant language 10 years ago, I would have laughed, and then vomited. Well, it is, and I still vomit when I think of it (personal opinion obviously, still would use it if I had to, and I have nothing against those that prefer it).

A lot of these silly absolutes about one language never ever replacing one over the other is nonsense. And honestly, who cares? If you do this kind of stuff (not necessarily game dev, but any kind of dev work) for a living, it's just a means to an end and a hopefully nice paycheque at regular intervals. Nothing more, nothing less.  On your own time, you write the stuff you want, in whatever you're most comfortable with. There's no need to even tell people what you write your stuff in, because it really doesn't matter as long it runs and runs smooth enough for most people.

I think of it this way: What would happen if I went into my workplace and demanded that my employer let me use C++ even though we're a VB6 shop because of reasons?  I'd likely be hauled into a meeting room, and told to drop it. And if I persisted, I'd likely be unemployed and rightfully so. 

I hate these kinds of topics, they end up devolving into a Language A vs. Language B war. Often this ends up with outright misinformation like C# being interpreted (which, by the way, is an interview question I give to candidates, and if you answer interpreted, you don't get hired) which then gets propagated everywhere as the gospel truth. And in these "wars", we see some people who have many years of experience that lack wisdom and just bark that their language was sent by the gods for reasons. And other people who have little to no experience just get roped in because that's what they read in some blog/forum or something, so it must be true.  Neither group is right.  The latter is more understandable due to a lack of practical experience. However, the former should be ashamed of themselves, they should know better and get out of this holier-than-thou, snorting, glasses pushing, super-nerd mindset. It's not a good look.

So please, let's just drop this silly topic and write off the whole thing as a bad idea yeah?

@Mods: Shouldn't this be in the Lounge or something?  This seems like a really poor fit for the Game Programming forum as it has little to do with actual programming and more to do with silly opinions.

On 8/25/2019 at 6:29 AM, Green_Baron said:

Is there really such a thing as a dedicated "runtime environment" for C or C++ ? I mean, there is the OS with its functionality for memory and io stuff, and driver routines that one can call. Also some routines to care for the stack (are these built into the executable program when linking ?) and other statically or dynamically linked libraries the program depends on.

Well hey, I'm a toolchain developer by profession, I feel qualified to answer that.

Yes, C has a runtime.  It's called "libc" (or MSVCRT/MSVCRTD on one special platform).  C programs are built using a memory model that rarely coincides wit hthe OS kernel's ideas of memory, and very rarely talk to drivers.  It's all done through the abstract layer provided by the libc runtime.  In addition, the toolchain will provide some embedded runtime code for application startup/teardown and a few other things related to the C memory model (like thread-local storage, atomics support, asynchronous signal handling, atexit handling, setjmp/longjmp, and some interactions with floating-point coprocessors).  Your toolchain driver will invisibly handle all the grohdy bits for you behind the scenes; few people are fully aware of what goes on below the abstract C machine.

Things like "the stack" in C are just implicit and part of the C abstract machine.  The OS is unaware of how the applicaiton is using its memory.  The C "heap" is part of the C runtime:  it usually uses a threadsafe caching slab allocator, but again the OS is unaware of how the application is using its memory.  Sometimes applications talk directly to drivers through a slim shim in the C runtime called "ioctl()" but more and more of that is done directly through the /proc filesystem on modern POSIX systems (I don't know how it's done on Windows) using just regular open/read/write calls provided by libc.

C++ has an even larger runtime to handle exceptions, RTTI, and of course there's the C++ standard library (no, it's not all templates and some common templates like std::string usually have concrete implementations in a shared object too).  The C++ standard library links to the C standard library, and C++ has a different startup/teardown than C (consider constructors and destructors for namespace-level objects with static or thread-local storage duration).

Interestingly, you'll find things like the .NET runtime and the Java runtime are written in C (or maybe C++) and are usually built on top of the C runtime.  That makes the runtimes very (compile-time) portable.

The C runtime has a Unix heritage (just like DOS/Windows, Mac OS, and Linux/Android do).  It's not the only way to do things.  There are development environments that do not build on libc.  For example, the Go language has it's own runtime that does not use libc.  Go is extremely portable as along as you're targeting an OS that Google supports. Some of that portability is because Go requires static linking, so the entire runtime is directly embedded in each and every applicaiton.  Ada is another such language:  it's Ada turtles all the way down to the kernel context switches.  It's possible to build a spycam or missile guidance system with no C on it at all.

Didn't mean to write an essay here, but it's not often I get to talk about what I do for a living to someone who may be remotely interested.

Stephen M. Webb
Professional Free Software Developer

Thanks for the clarification, i learned something !

51 minutes ago, Bregma said:

Well hey, I'm a toolchain developer by profession, I feel qualified to answer that.

Yes, C has a runtime.  It's called "libc" (or MSVCRT/MSVCRTD on one special platform).  C programs are built using a memory model that rarely coincides wit hthe OS kernel's ideas of memory, and very rarely talk to drivers.  It's all done through the abstract layer provided by the libc runtime.  In addition, the toolchain will provide some embedded runtime code for application startup/teardown and a few other things related to the C memory model (like thread-local storage, atomics support, asynchronous signal handling, atexit handling, setjmp/longjmp, and some interactions with floating-point coprocessors).  Your toolchain driver will invisibly handle all the grohdy bits for you behind the scenes; few people are fully aware of what goes on below the abstract C machine.

Things like "the stack" in C are just implicit and part of the C abstract machine.  The OS is unaware of how the applicaiton is using its memory.  The C "heap" is part of the C runtime:  it usually uses a threadsafe caching slab allocator, but again the OS is unaware of how the application is using its memory.  Sometimes applications talk directly to drivers through a slim shim in the C runtime called "ioctl()" but more and more of that is done directly through the /proc filesystem on modern POSIX systems (I don't know how it's done on Windows) using just regular open/read/write calls provided by libc.

C++ has an even larger runtime to handle exceptions, RTTI, and of course there's the C++ standard library (no, it's not all templates and some common templates like std::string usually have concrete implementations in a shared object too).  The C++ standard library links to the C standard library, and C++ has a different startup/teardown than C (consider constructors and destructors for namespace-level objects with static or thread-local storage duration).

Interestingly, you'll find things like the .NET runtime and the Java runtime are written in C (or maybe C++) and are usually built on top of the C runtime.  That makes the runtimes very (compile-time) portable.

The C runtime has a Unix heritage (just like DOS/Windows, Mac OS, and Linux/Android do).  It's not the only way to do things.  There are development environments that do not build on libc.  For example, the Go language has it's own runtime that does not use libc.  Go is extremely portable as along as you're targeting an OS that Google supports. Some of that portability is because Go requires static linking, so the entire runtime is directly embedded in each and every applicaiton.  Ada is another such language:  it's Ada turtles all the way down to the kernel context switches.  It's possible to build a spycam or missile guidance system with no C on it at all.

Didn't mean to write an essay here, but it's not often I get to talk about what I do for a living to someone who may be remotely interested.

I think what natively compiled languages use is way different than what you have in languages such as C# and Java.  The former just uses a set of libraries that are linked in. There is no special external environment necessary to run a program once it's compiled, except possibly where DLLs are used.  However that functionality is part of the base OS support, and you can typically statically link things anyway if you want to. Also the "stack" is generally supported by hardware instructions. It's even lower level than the OS. You use the stack in assembly language just like you would in C, C++ or Fortran.  Maybe what you are referring to are "calling conventions" (i.e. how the stack is used to pass around parameters) which can vary between languages.  If you ever try to call asm from C or C++, that's something you have to know.

11 hours ago, Gnollrunner said:

the "stack" is generally supported by hardware instructions. It's even lower level than the OS. You use the stack in assembly language just like you would in C, C++ or Fortran

When you throw an exception in C++ and it gets caught, how does the machine language instruction know to execute the destructors in all the intervening contexts to implement the miracle of RAII?  When I'm writing assembly, which mnemonic do I use to do that?

You might be surprised by just how much C runtime there is.  You might also be surprised that not every OS bundles the C runtime, since it's not in fact a part of the base OS support.  It just happens to always be installed on machines you have experience with.  On the flip side, I've dealt with plenty of embedded systems developed without an OS but written in C.

Stephen M. Webb
Professional Free Software Developer

12 hours ago, Gnollrunner said:

I think what natively compiled languages use is way different than what you have in languages such as C# and Java.  The former just uses a set of libraries that are linked in.

You seem to want to make a distinction between 'libraries' and 'environment'. It's all the same thing.
 

3 hours ago, Prototype said:

You seem to want to make a distinction between 'libraries' and 'environment'. It's all the same thing.
 

I make a distinction because of the way it's handled . For instance in Java, you run your program with another program.  I can take a C++ program compiled on windows to another windows machine and simply click on the exe with nothing special on my system.  The same goes for machines with UNIX.  I can do the same with Fortran and the OS really won't know the difference. In the case of C# Microsoft ships the support with the OS since it's a MS product. They also do some wrapping so it looks like an exe.

I should add, this sounds like it's getting into a semantics discussion.

5 hours ago, Bregma said:

When you throw an exception in C++ and it gets caught, how does the machine language instruction know to execute the destructors in all the intervening contexts to implement the miracle of RAII?  When I'm writing assembly, which mnemonic do I use to do that?

You can defiantly unroll the stack in ASM. There isn't necessarily a single mnemonic to do everything you want to do, but the concept of a stack is there on most modern hardware. On intel machines there is a special register for it and there are special instructions that deal with it.  Even in 8086 machines that's still true. When you load an executable file the loader has to initialize the stack. What the OS "knows" about depends on how you want to interpret it.

This topic is closed to new replies.

Advertisement