why is C++ not commonly used in low level code?
#22 Moderators - Reputation: 3969
Posted 18 July 2011 - 06:27 AM
before working out that they agree OO is the root of all evil.
Then two people would be wrong, yay!
There is nothing wrong with OO done correctly, the 'problem' is the lack of design skills, critial thinking and correctly applying paradigms to solve a problem.
The problem is most people don't have those skills but then again chances are they would write bad code in any paradigm if left to their own devices...
#23 Members - Reputation: 1565
Posted 18 July 2011 - 07:07 AM
There is nothing wrong with OO done correctly, the 'problem' is the lack of design skills, critial thinking and correctly applying paradigms to solve a problem.
The problem is most people don't have those skills but then again chances are they would write bad code in any paradigm if left to their own devices...
Oh, I agree. I've just always found it funny that many c programmer's arguments against c++ revolve around inheritance, when the guy who designed the STL has pretty much the same opinion!
In the linked rant (in between attempts at trolling) Torvalds says similar to what you say about lack of skills. Stepanov, for all his hatred of OO, presumeably likes that in c++ you can have a function object whose operator() can be inlined, unlike a c function ptr. So he doesn't mind objects, just OO......
Personally, I think the problem is that 'OO done correctly' means different things in different languages and different problem spaces, which has lead to people having the skills and wanting to apply them, but applying them wrongly for c++ in performance-critical situations. There's a wealth of OO design wisdom out there, and while most of it can be applied to c++ design, not all of it should have been. For example, classical OO literature revolves around using inheritance for polymorphism, which is not always the best way to go in c++ where we have lovely compile-time polymorphism.
(insert obligatory comment about OO being possible in c and the OO argument therefore being irrelevant to this thread anyway - if I didn't someone else would!)
#24 Members - Reputation: 150
Posted 18 July 2011 - 09:29 AM
Before making my way back to game development i spent many years writing an irc daemon (ircd). I was often beset with idiots telling me that because i had chosen to write such a program in C++, it simply would not scale, would take all available RAM in the server, that inheritence would make it slow, and other quite frankly stupid arguments.
Needless to say most of these people did not believe that you should choose the right tool for the job. In this particular case, the right tool for the right job, based on my skillsets and the requirements of the application, were C++.
If i was to approach the same problem again today maybe i would not choose C++, but i definitely still would not choose C.
Firework Factory - Casual Puzzler for Xbox 360 and PC | Judgement Call - Online Roleplayer for PC | More Information
#25 Members - Reputation: 116
Posted 18 July 2011 - 09:38 AM
1) Portability. C is the most portable language out there.
2) Simplicity. Most low level code does not require C++ features.
3) Efficiency. C code is often both faster and smaller than C++ code. There's a reason why there are no interesting 1k/4k demos written in C++, because it is shit for size optimized code.
The interesting question would be "Why should anyone use C++ in low level code?".
Note that with C++ code I actually mean proper OO+exceptions+templates kind of code. Sure, you can write pure C and compile it with C++ compiler and claim that "Oh but it IS valid C++!" but it defeats the whole purpose of the discussion.
This opinion that C is 'better than' C++ for various problem domains is rampant in the open source community.
Before making my way back to game development i spent many years writing an irc daemon (ircd). I was often beset with idiots telling me that because i had chosen to write such a program in C++, it simply would not scale, would take all available RAM in the server, that inheritence would make it slow, and other quite frankly stupid arguments.
Needless to say most of these people did not believe that you should choose the right tool for the job. In this particular case, the right tool for the right job, based on my skillsets and the requirements of the application, were C++.
If i was to approach the same problem again today maybe i would not choose C++, but i definitely still would not choose C.
This is because you don't care about portability. You only wanted your ircd run on your own system.
I myself write code which has to run from routers to super computers, so anything except C is a definite no-go for me, because the code HAS to compile on those machines which run operating systems and CPU and hardware architectures unknown to me. Everything I care about is conforming to C89, POSIX and SUS(Single Unix Specification) standards.
#26 Members - Reputation: 2408
Posted 18 July 2011 - 09:55 AM
C code is often both faster and smaller than C++ code.
Again, examples please. These spurious claims are making the thread feel like groundhog day.
Note that with C++ code I actually mean proper OO...
You probably don't mean "proper" OO, which is entirely possible in almost any language.
...+exceptions+templates kind of code.
Aargh. Templates do not cause overhead. Having multiple versions of a function for different types is not overhead, if those multiple versions are required. Writing and maintaining several versions of a function does cause overhead - programmer overhead, e.g. time, money and sanity.
Sure, you can write pure C and compile it with C++ compiler and claim that "Oh but it IS valid C++!" but it defeats the whole purpose of the discussion.
Yeah, you can also write C++ code that uses none of the supposedly expensive features above, no additional overhead compared to a C program and all the added benefits of type safety.
There are only two sane reasons to prefer C over C++ in my view - a) there does not exist a well-proven C++ compiler for a given platform or b) the programmers available for the job at an acceptable cost are experienced in C, not C++.
Both are valid real-world reasons. Neither have anything whatsoever to do with the nature of C++, except possibly its younger age than C.
And, as a footnote, all of Linus T's arguments seem to be about C++ programmers, not about C++. But then I haven't written an operating system filled with comments like "// this is a hack, we have no idea how it works" so what do I know?
#27 Members - Reputation: 150
Posted 18 July 2011 - 10:29 AM
This is because you don't care about portability. You only wanted your ircd run on your own system.
I myself write code which has to run from routers to super computers, so anything except C is a definite no-go for me, because the code HAS to compile on those machines which run operating systems and CPU and hardware architectures unknown to me. Everything I care about is conforming to C89, POSIX and SUS(Single Unix Specification) standards.
I am sorry but this is an incorrect and hastily entered response. The software in question is extremely popular, in use by many hundreds of networks, and definitely not just designed 'for my own computer'. I myself run a 600 user network on it and there are many other networks of 3000 users and up that use the same software. Maybe you should take a look at the project website (http://www.inspircd.org) and reconsider your kneejerk response to my post.
Firework Factory - Casual Puzzler for Xbox 360 and PC | Judgement Call - Online Roleplayer for PC | More Information
#28 Senior Moderators - Reputation: 3113
Posted 18 July 2011 - 11:44 AM
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX
#29 Members - Reputation: 116
Posted 18 July 2011 - 12:17 PM
Here's a simple example:
C:
#include <stdio.h>
int main(int argc, char *argv[]) {
int i=0;
int j=0;
char name[32];
for(i=0;i<8192;i++) {
printf("Argument count: %d\n", argc);
for(j=0;j<argc;j++) {
printf("Name: %s\n", argv[j]);
}
}
scanf("%32s", (char*)&name);
printf("Hello %s!\n", name);
return 0;
}
C++:
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
std::string name;
for(int i=0;i<8192;i++) {
std::cout << "Argument count: " << argc << std::endl;
for(int j=0;j<argc;j++) {
std::cout << "Name: " << argv[j] << std::endl;
}
}
std::cin >> name;
std::cout << "Hello " << name << "!" << std::endl;
return 0;
}
results:
[calmis@purpleorange cvscpp]$ g++ main.cpp -o main2 -O0 -Wall -Wextra
[calmis@purpleorange cvscpp]$ gcc main1.c -o main1 -O0 -Wall -Wextra
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main2 a ab abc abcd abcde abcdef abcdefg > mainCPP.txt
real 0m0.314s
user 0m0.063s
sys 0m0.203s
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main1 a ab abc abcd abcde abcdef abcdefg > mainC.txt
real 0m0.046s
user 0m0.023s
sys 0m0.000s
[calmis@purpleorange cvscpp]$ wc -c main2
8048 main2
[calmis@purpleorange cvscpp]$ wc -c main1
5213 main1
Size optimizations turned on:
[calmis@purpleorange cvscpp]$ g++ main.cpp -o main2 -Os -s -Wall -Wextra
[calmis@purpleorange cvscpp]$ gcc main1.c -o main1 -Os -s -Wall -Wextra
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main2 a ab abc abcd abcde abcdef abcdefg > mainCPP.txt
real 0m0.326s
user 0m0.043s
sys 0m0.227s
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main1 a ab abc abcd abcde abcdef abcdefg > mainC.txt
real 0m0.035s
user 0m0.023s
sys 0m0.000s
[calmis@purpleorange cvscpp]$ wc -c main2
5132 main2
[calmis@purpleorange cvscpp]$ wc -c main1
3508 main1
9.3x faster, some 1.4x smaller.
C functions with void* arguments and a variable to denote the types, and then using switch() to invoke right code(assuming that e.g. 8, 16, 32 and 64 bit ints can share the same code) is more size-efficient than C++ with templates.
I rest my case for now.
#30 Members - Reputation: 941
Posted 18 July 2011 - 12:31 PM
Also, to make the code a little closer to the C version, reserve some memory for the string.
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
std::string name;
name.reserve(32);
for(int i=0;i<8192;i++) {
std::cout << "Argument count: " << argc << '\n';
for(int j=0;j<argc;j++) {
std::cout << "Name: " << argv[j] << '\n';
}
}
std::cin >> name;
std::cout << "Hello " << name << "!" << std::endl;
return 0;
}
C++
real 0m0.042s
user 0m0.030s
sys 0m0.010s
C
real 0m0.029s
user 0m0.020s
sys 0m0.007s
[edit]
Added link about std::endl.
#31 Members - Reputation: 2369
Posted 18 July 2011 - 12:43 PM
9.3x faster, some 1.4x smaller.
Wrong conclusion.
The problem is IO bound, so heuristics on buffer sizes will determine the running time.
Change those std::endl to '\n' and you see a big difference.
Also disable sync with stdio, I forgot exactly how. I think it's disable_sync_with_stdio() or similar.
#32 Members - Reputation: 150
Posted 18 July 2011 - 01:09 PM
Every language has specific traits that outweigh some other language, and this is what matters. In the end, holy wars with 'X vs Y' do nothing but serve to cause arguments and usually are based in nothing but heresay and personal opinion without solid proof.
Use the right tool to solve the problem, without trying to use an excavator to swat a fly, and you will prosper. :-)
(EDIT: 1.6 million google results are here saying why it is not a good idea to trust such benchmarks).
Edited by braindigitalis, 18 July 2011 - 01:11 PM.
Firework Factory - Casual Puzzler for Xbox 360 and PC | Judgement Call - Online Roleplayer for PC | More Information
#33 Members - Reputation: 116
Posted 18 July 2011 - 01:09 PM
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main1 a ab abc abcd abcde abcdef abcdefg > mainC.txt
real 0m0.035s
user 0m0.017s
sys 0m0.007s
[calmis@purpleorange cvscpp]$ time echo "Dun-dun Daa" | ./main2 a ab abc abcd abcde abcdef abcdefg > mainCPP.txt
real 0m0.055s
user 0m0.033s
sys 0m0.003s
Obviously the speed bottleneck in this case is/was due to a incompetent programmer(me). However, there's still the size problem to solve. With GCC 4.6 the sizes are:
[calmis@purpleorange cvscpp]$ wc -c main1
3508 main1
[calmis@purpleorange cvscpp]$ wc -c main2
5944 main2
...when compiled with -Os and -s flags. This is my main point when working with embedded systems which do not necessarily have the resources to spare for increased code size.
But as stated numerous times before, the main reason for preferring C over C++(at least to date) has been with portability and habit.
I don't think you are able to measure the performance of a language with an artificial benchmark such as this. An artificial benchmark can be designed to prove that any X is 'better than' Y for any specific benchmark.
Every language has specific traits that outweigh some other language, and this is what matters. In the end, holy wars with 'X vs Y' do nothing but serve to cause arguments and usually are based in nothing but heresay and personal opinion without solid proof.
Use the right tool to solve the problem, without trying to use an excavator to swat a fly, and you will prosper. :-)
This is completely true. It is not possible to draw conclusions about the whole language based on single benchmarks really. However, I was asked for an example which demonstrates that C indeed is more resource efficient than C++, and I brought in one, very simple example of this. And it gets even worse when one starts using more than just the standard C++ library, e.g. classes, multiple inheritance and exceptions. This is based on my experience when working with 1k/4k demoscene prods, in which C++ is a definite no-go because of the increased resulting binary size. If size doesn't matter(what!?), then C++ is much more attractive for me at least. But as shown above, I am not a C++ dev at all really.
#34 Moderators - Reputation: 7768
Posted 18 July 2011 - 01:19 PM
[Work - ArenaNet] [Epoch Language] [Scribblings] [Journal - peek into my shattered mind]
#35 Members - Reputation: 150
Posted 18 July 2011 - 01:20 PM
This is based on my experience when working with 1k/4k demoscene prods, in which C++ is a definite no-go because of the increased resulting binary size.
Ahh, the nostalgia, i remember when these were written in assembly language, not C
Firework Factory - Casual Puzzler for Xbox 360 and PC | Judgement Call - Online Roleplayer for PC | More Information
#36 Members - Reputation: 116
Posted 18 July 2011 - 01:39 PM
Did you remember to strip symbols and debug information from your binary after you compiled it?
With external tools? Not really, but after doing that the results are as follows:
[calmis@purpleorange cvscpp]$ wc -c main1
3508 main1
[calmis@purpleorange cvscpp]$ wc -c main2
5944 main2
[calmis@purpleorange cvscpp]$ strip -R .comment -R .gnu.version main1
[calmis@purpleorange cvscpp]$ strip -R .comment -R .gnu.version main2
[calmis@purpleorange cvscpp]$ sstrip main1
[calmis@purpleorange cvscpp]$ sstrip main2
[calmis@purpleorange cvscpp]$ wc -c main1
2048 main1
[calmis@purpleorange cvscpp]$ sstrip main2
[calmis@purpleorange cvscpp]$ wc -c main2
4424 main2
The reason why I excluded this in the first place was that when working with embedded systems often there are no such tools to use, so they'd just skew the results.
This is based on my experience when working with 1k/4k demoscene prods, in which C++ is a definite no-go because of the increased resulting binary size.
Ahh, the nostalgia, i remember when these were written in assembly language, not C
These days optimizing compiler can generate pretty much quite damn optimal assembly from C, and OS-specific tricks and external strippers/packers/crunchers have advanced very much during the past few years or so to further reduce the gap between C and asm. Writing a barebone sketch with C and optimizing the rest by hand in asm is the way to go.
#37 Moderators - Reputation: 3969
Posted 18 July 2011 - 02:07 PM
1) std::cin and std::cout are doing more than the scanf and printf under the hood, which are both valid C++ functions btw and thus any coder worth their salt would use them if the situation required it*
2) As soon as the input string exceeds 32 characters your C code runs the risk of blowing up nicely; the C++ version is safe in that regard.
(* it becomes a speed vs safety trade off... if you want speed then you'd take the functions with the lowest overhead, if you want safey then you have to ditch some of that speed)
#38 Members - Reputation: 2763
Posted 18 July 2011 - 02:27 PM
There's also a certain amount of historical bias / tribalism among codgy old embedded developers, who probably gave up assembly with a fair bit of reluctance. In the wide, this means that much of the ecosystem is built around C. C++ is making inroads on more capable platforms (eg, MIPS/PowerPC platforms), but C is still king elsewhere, and probably will be for quite some time.
It's also true that, when a custom solution is called for, its far more straight-forward to build something on top of C, than to try to undo/work around what C++ has by default and replace it with your own -- I'm not talking about memory allocation here, I mean things like providing some sort of (psuedo-)object system built to be performant on the device.
You're right that C++ does have quite a few other features that are useful to embedded dev though -- for example, you could concievably use placement new to initialize memory-mapped devices using the class constructor, and template meta-programming can be used to generate highly-tuned code parametrically.
#39 Members - Reputation: 230
Posted 18 July 2011 - 03:24 PM
So, if you're writing code, and all of the domain momentum is geared toward C (existing code, libraries, developer skillsets), it's very difficult to justify moving to C++. It's a similar situation with C++ vs a higher level language for games.
#40 Moderators - Reputation: 13585
Posted 18 July 2011 - 06:47 PM
As mentioned by phantom, that's a completely false benchmark, as both programs aren't doing the same thing at all, you've made the C++ one do a ton more work than the C one.I rest my case for now.
You may as well have written:
//C benchmark
for( int i=0; i<1; ++i ){printf("");}//C++ benchmark
for( int i=0; i<10000; ++i ){printf("");}That's a completely false argument -- the C equivalent of virtual functions are function pointers. The C equivalent of templates are #include-templates.Mostly because C++ doesn't help solve the problems that "low level code" is facing. It's considerably easier to guess what's going on under the hood with a C program compared to a C++ program. Virtual functions make it difficult to determine what code will run next. Templates make it difficult to determine what code even exists.
If you used those same methodologies in both languages, you'd have the same problems in both languages.
Not all C++ programs are written using the wrong features at the wrong time. Just because you're using C++ everywhere, it doesn't mean you should go and use virtual for something where you wouldn't have used a function-pointer in C. If you do, then you're just a shit C++ programmer, and the argument becomes "good programmers are better than shit programmers, derp!".
This topic is locked





