Do you have any proof of that? Links to measurements, etc? Because all the cool guys thinks otherwise (Stallman, Linus, ESR, etc.). Hell, even it's creator, Stroustrup admitted in an interview, that C++ supposed to be a joke.freem {l Wrote}:For a start, C++ can outperform C in many aspects.
Stroustrup: Well, it’s been long enough, now, and I believe most people have figured out for themselves that C++ is a waste of time but, I must say, it’s taken them a lot longer than I thought it would.
Not true. Okay might be true in some special edge cases, but not for your example for sure. As long as sort concerned, there's only one comparator call needed, and both C and C++ compilers are capable to inline that. On the other hand using templates in C++ involves an additional abstraction layer with virtual method calls, while in C that's just a simple function call like any other.
And I'm pretty sure there is. The most common problem with C++ that it is OOP, meaning it is pretty heavy on memory allocation, calling new and delete all the time, repeatedly. No C++ compilers can eliminate that handycap, but it return since the language extremely poorly designed, C++ compilers are unbelievably SLOOOOOOOOOW... (there are some optimizations in the allocators, not in the compiler to mitigate that unavoidable OOP handycap. See jemalloc for example, it is anything but simple.)freem {l Wrote}:In the past, C++ had worst performances than C, because compilers were not as mature, but I do not think there's still such a big difference nowadays (if any).
Challenge accepted! Please write any C++ code for desktop, show me the code and I guarantee that I can write a counterpart in C which will compile much faster and will run and perform much faster than your C++ version. Come on, it's going to be fun! Let's do measurements for evidence.freem {l Wrote}:The only place where C can arguably beat C++ is on micro-controllers
#include <algorithm>
#include <functional>
#include <array>
#include <iostream>
#include <string_view>
int main()
{
std::array<int, 10000> s = {5100,1324,4556,2001,8619,545,3952,9570,6956,...753,3130,2604,5276};
auto print = [&s](std::string_view const rem) {
for (auto a : s) {
std::cout << a << ' ';
}
std::cout << ": " << rem << '\n';
};
std::sort(s.begin(), s.end());
print("sorted with the default operator<");
}
#include <stdio.h>
#include <stdlib.h>
#define LEN(a) (sizeof(a)/sizeof(a[0]))
int cmp(const void *a, const void *b) { return *((int*)a) - *((int*)b); }
int main(int argc, char **argv)
{
int i, s[10000] = {5100,1324,4556,2001,8619,545,3952,9570,6956,...753,3130,2604,5276};
qsort(s, LEN(s), sizeof(int), cmp);
for(i = 0; i < LEN(s); i++)
printf("%d ", i);
printf(": sorted qith C qsort\n");
}
$ time gcc sort.c -o sortc
real 0m0.077s
user 0m0.056s
sys 0m0.019s
$ time g++ sort.cpp -o sortcpp
real 0m0.478s
user 0m0.417s
sys 0m0.055s
$ du -h sortc sortcpp
60K sortc
72K sortcpp
$ (time ./sortc) &>sortc.txt
$ cat sortc.txt | grep real
real 0m0.005s
$ (time ./sortcpp) &>sortcpp.txt
$ cat sortcpp.txt | grep real
real 0m0.012s
On the other hand using templates in C++ involves an additional abstraction layer with virtual method calls, while in C that's just a simple function call like any other
The most common problem with C++ that it is OOP, meaning it is pretty heavy on memory allocation, calling new and delete all the time, repeatedly.
while debugging C++ code is a major PITA, and not just because of the name mangling
If two members compare as equal, their order in the sorted array is undefined.
for i in $(seq 1 10000); do od -A n -t d -N 4 /dev/urandom; done > /tmp/data
#include <stdio.h>
#include <stdlib.h>
#define LEN(a) (sizeof(a)/sizeof(a[0]))
int cmp(const void *a, const void *b) { return *((int*)a) - *((int*)b); }
int main()
{
int s[] = { /* data generated by urandom and inserted in source code */ };
qsort(s, LEN(s), sizeof(int), cmp);
for(int i = 0; i < LEN(s); i++)
printf("%d ", i);
printf("\n");
}
% clang test.c -o cc && time (for i in $( seq 1 10000 ); do ./cc > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cc > /dev/null; done; ) 17,82s user 2,74s system 102% cpu 20,075 total
% clang -Os test.c -o cc && time (for i in $( seq 1 10000 ); do ./cc > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cc > /dev/null; done; ) 15,47s user 2,88s system 102% cpu 17,874 total
#include <algorithm>
#include <iterator>
#include <stdio.h>
int main()
{
int s[] = { /* data generated by urandom and inserted in source code */ };
std::sort( std::begin( s ), std::end( s ), []( int a, int b ){ return a < b; } );
for( int i : s )
printf("%d ", i);
printf("\n");
}
% clang++ test.cpp -o cpp && time (for i in $( seq 1 10000 ); do ./cpp > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cpp > /dev/null; done; ) 25,15s user 4,61s system 101% cpu 29,278 total
% clang++ -Os test.cpp -o cpp && time (for i in $( seq 1 10000 ); do ./cpp > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cpp > /dev/null; done; ) 15,13s user 3,50s system 102% cpu 18,143 total
#include <stdio.h>
#include <stdlib.h>
#define LEN(a) (sizeof(a)/sizeof(a[0]))
int cmp(const void *a, const void *b) { int ret = *((int*)a) - *((int*)b); return ret == 0 ? -1 : ret; }
int main()
{
int s[] = { /* data generated by urandom and inserted in source code */ };
qsort(s, LEN(s), sizeof(int), cmp);
for(int i = 0; i < LEN(s); i++)
printf("%d ", i);
printf("\n");
}
% clang test.c -o cc && time (for i in $( seq 1 10000 ); do ./cc > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cc > /dev/null; done; ) 17,17s user 3,00s system 102% cpu 19,691 total
% clang -Os test.c -o cc && time (for i in $( seq 1 10000 ); do ./cc > /dev/null; done)
( for i in $( seq 1 10000 ); do; ./cc > /dev/null; done; ) 15,87s user 2,88s system 102% cpu 18,271 total
% time clang -Os test.c
clang -Os test.c 0,06s user 0,00s system 99% cpu 0,068 total
% time clang++ -Os test.cpp
clang++ -Os test.cpp 0,31s user 0,02s system 99% cpu 0,335 total
% clang++ -static -Os -fno-rtti -fno-exceptions test.cpp -o cpp && strip cpp
% clang -static -Os -fno-rtti -fno-exceptions test.c -o cc && strip cc
% ls -lh cc cpp
ls -lh cc cpp
-rwxr-xr-x 1 ... ... 771K 11 oct. 11:34 cc
-rwxr-xr-x 1 ... ... 775K 11 oct. 11:34 cpp
bzt {l Wrote}:Hell, even it's creator, Stroustrup admitted in an interview, that C++ supposed to be a joke.
First, constructor allocating memory and destructor freeing it is part of any OOP language, there's nothing you could do about it. Good programmer or bad programmer doesn't matter, you must use "new" one way or another with objects, no escape.freem {l Wrote}:This is the mark of bad C++ programming. Average skill C++ programmers don't realloc everytime they add elements to a vector... thankfully!
Both only printing to kernel buffered stdout, so I/O overhead should be the same. But okay, let's remove that print, I agree the results would be more accurate that way.freem {l Wrote}:Also, your example is *not* measuring only the difference between sort and qsort, as it includes I/O, notably from the shitty streambuf lib.
Absolutely not. People are too often and too quickly throwing in the phrase "UB".freem {l Wrote}:So your C code is basically going to trigger undefined behaviors
I've just copy'n'pasted the "time" output. It was twice as fast on my computer.freem {l Wrote}:So, you're right, it seems a bit slower. Not twice, though.
First, there's no UB with the subtraction at all. Second, your code does have exactly the same subtraction, so if there really were an UB here, your code would have exactly the same UB too, you have fixed nothing (but you have introduced an unoptimizable trinary conditional and an additional stack local variable without any reason).freem {l Wrote}:Fixing the UB in C code would slow it down a lot, as this involves a condition. Let's give it a try:
- {l Code}: {l Select All Code}
int cmp(const void *a, const void *b) { int ret = *((int*)a) - *((int*)b); return ret == 0 ? -1 : ret; }
Which is one of the disadvantages of C++ that I hate the most. It not only kills productivity by having to wait for the computer, but also always derails my "creative mindset" (I don't know how to explain this, it's like having a flat tire around every other corner.)freem {l Wrote}:As expected, C++ takes longer to compile.
dulsi {l Wrote}:Languages are to enable building the program. I'm sure you can come up with scenarios where X is better than Y regardless of the value of X and Y. Just make games and leave the language tribalism to other sites.
Yes, this is well-known meme. I've used the wording "supposed to be", and used that link deliberately instead of the original catv link, just in case someone isn't familiar with the meme.PeterX {l Wrote}:There at the link you gave it says it was a fake interview!
Wow, do you have a link to Knuth's stance by any chance? That would be huge, a great argument backing up my claims. Not many ppl are qualified to question Knuth on programming languages :-)PeterX {l Wrote}:I think as @bzt about C++. As does Prof. emer. Knuth.
Yeah, at least that is what they say. In reality I always piss blood with code that has to compile with gcc and g++ as well. Closer to the truth is, there's a small, hacked subset of the C language that works with both.PeterX {l Wrote}:One good thing about C++ is that it supports nearly 100% of C.
C++ is too complicated. At the moment, it's impossible for me to write portable code that I believe would work on lots of different systems, unless I avoid all exotic features. Whenever the C++ language designers had two competing ideas as to how they should solve some problem, they said "OK, we'll do them both". So the language is too baroque for my taste
jdc {l Wrote}:If you do a game in C what will happen is that people will still play it in 2022
Ah, this isn't a technical argument, just an opinion. That's a pity, but better than nothing.PeterX {l Wrote}:Here's what Prof. Knuth said:
Yep, I've never questioned that. I'm just pointing out that programs written in C++ will always be worse performance-wise, simply because there are language features which need run-time support (and with that, will always add run-time overhead). And, because the language hides from the programmer which parts need those run-time support, an average joe will always fall into using them without realizing the performance impact.PeterX {l Wrote}:But please let's accept the fact that C++ is good for some programmers.
Come on, dulsi, as someone who enjoys reviving old games you know this isn't true. Your game has lot better chance to compile 30 years later if it's in C than if it's in any other language (like QBasic or Cobol for example).dulsi {l Wrote}:No. No one cares what language your game is in.
Vulkan is written in C and not C++. Even though there's a (terrible and ineffective) C++ wrapper API, this means it does not really use any of the C++ language features, and in return the vulkan library can be accessed from any C ABI compatible programming language. See this tutorial about the Vulkan C (not C++) API.jdc {l Wrote}:Vulkan updated C++ code it look atractive.
bzt {l Wrote}:Come on, dulsi, as someone who enjoys reviving old games you know this isn't true. Your game has lot better chance to compile 30 years later if it's in C than if it's in any other language (like QBasic or Cobol for example).dulsi {l Wrote}:No. No one cares what language your game is in.
Ah, I see, that's true. But I'm still curious how one would run a Rust application in 10 years from now without recompilation, considering its ABI is a moving target. I can run an executable that I compiled 10 years ago from a C source without probs (as long as that horrible glibc versioned function names feature not used, but that's not the C language's fault).dulsi {l Wrote}:Well I was specifically responding to "people will keep playing your game if it is in C". Players don't care what language your game is in. It just needs to be easy to run and that depends on how you package it for them/
This isn't so. ANSI C has changed a lot over the years, it's just all the changes were done by experts and the smart way, keeping backward compatibility.dulsi {l Wrote}:Sure C is easy to compile 30 years later because the language hasn't changed in 30 years.
Well, yes and no. This is a tough question. Pthread is basically part of the language (as well as threads.h for later sources), so much so that many libc implementation includes it out-of-the-box (for example musl, where threads.h is just a wrapper around pthreads). But you're right in a way, because POSIX specifies pthreads not ANSI C, and sadly there's no clear boundary where the ANSI C spec ends and POSIX starts. It would be more fortunate if the language and the underlying OS interface would have been clearly separated from the start. This is an issue with C, I give you that. Luckily all non-POSIX OS have wrappers (most notably Win32 API has cygwin and mingw as well) to provide a common libc interface for the language.dulsi {l Wrote}:If I want to create a thread, the language can't do it. You have to add pthread or some other library.
Yes, library dependencies are a headache. Luckily C has lots of well-maintained and multiplatform libraries, like SDL for example (which has SDL_Threads, so threading is a non-issue with that, no matter the OS.) X11 is pretty persistent and hasn't changed much over the years, but indeed there was a minor break in the API when xfree86 was replaced by xorg. (For example, here's xstoneage, which I originally wrote for xfree86. I had to change the window calls a bit to get it working with xorg, but the rest (Ximage, GC etc.) works unmodified.) I'm surprised that you had issues with the color mode, because that's a part of X11 that notoriously kept backward compatibility (and received the most critisism btw, because it is a considerably big part of any x server implementation although nobody has or needs a 2 colors or 16 colors visual any more.)dulsi {l Wrote}:If you want to do graphics that's another library. Could I compile Thrust? Sure but I couldn't run it because it used X11 psuedo-color mode.
Interesting, I have exactly the opposite experience (but I admit this highly depends on what projects you try to revive.) Last time I've modified Scorched3D so that I can compile it with the latest compiler and latest libs, and it wasn't a piece of cake... I've lost more hair during the process than I prefer to admit. (But you're right, most problems were library dependency related, not language related.)dulsi {l Wrote}:In my experience, compiling old C++ code is typically pretty easy. You get a few errors but they are easy to fix. The big problem are libraries that break compatibility. Granted modern C++ can't do graphics by itself yet and may never get that functionality. But I do like the threading functionality and improved random number generators.
jdc {l Wrote}:Nice that we have one more engine to tweek. People that said that learning C is not that good may be a bit disapointed now; whent to high paid frameworks like Unity Unreal when they have a good option in open source.
jdc {l Wrote}:Ya right, they make experiments on you if you do get to design a high quality game they get a high % and the better features are in the paid version. You can't acess the source code, so you will not learn nothing from using these engines. Become dependent on them.
Users browsing this forum: Google [Bot] and 1 guest