I love C. What's there not to love about this language, it's fast — mostly can be 1-1 translated into native code, portable and it's minimalist — you don't need to learn all these newfangled language constructs like those in Java, with C you can learn the syntax in a day or less. However, C has major limitations as a modern language, there's no native support for classes (you'd have to do long function declarations in order to get methods, and forget about property access protection lest you hack it in), there's no native support for automatic memory management like smart pointers or garbage collection (though BoehmGC can do that) and don't get me started on the ancient macro system — which is basically a wrapper of the Find-Replace function in text editors.
This is probably why C++ was created. All of which I
mentioned earlier had been solved, with actual runtime
classes, smart pointers through <memory>
header and templates allowing for easier code generation. Of
course, this all comes with a cost, compiling takes a lot
longer, in fact, here are the hard numbers when for a simple
Hello World program:
Language | Code | Time |
C |
|
|
C++ |
|
|
Most of this is due to the standard library's (in my case GNU's) headers — which heavily use templates and are highly dependent on each other. In addition, stdlib classes have deep inheritance trees, when they don't really need to be. If you just count the number of lines of the source files post-processed, you end up with 28257 lines for C++, as opposed to 719 lines for C. No wonder it's 10x faster to compile in C than in C++.
"Orthodox C++ is a minimal subset of C++ that improves C, but avoids all unnecessary things from so called Modern C++." Simply put, it's C++, but you can't use RTTI (runtime type information), exceptions or anything in the C++ stdlib, only the C standard library with modern C++ language features sprinkled in. Is it perfect for my use? Let's find out by writing a simple HTTP request application.
There is no good way of compiling C++ without the standard
library in GCC, unless you disable all the linker flags and
add your own. I ended up compiling the program by using
g++
to generate object files and
gcc
to link it all together.
To allocate/deallocate memory on the heap, you'd have to
call malloc and free in C. There's none of that in C++ of
course, you have to use the new and delete operators. To fix
this, you can simply shim the functions by aliasing
operator new
and operator delete
to
malloc
and free
respectively.
(thanks
pts.blog)
One thing to note that there's no standardized data
structure library for C, so you can't just create a class
wrapper around some functions and call it a day. Sure, there
are BSD macros, however it doesn't seem too integrated with
C++, you might as well write C at that point. So I decided to
rewrite the
standard library, well the part of the standard library
that I would be using that is. I've implemented classes for
std::vector
, std::string
and
std::unique_ptr
. I decided not to write classes
for std::cout
since the printf
family does all I want to. This is also an incorrect
implementation of the standard, for instance,
std::string
is just an
std::vector<char>
, however, it will work
for most common uses.
And lo and behold, here's my code! Nothing to fancy, it can just pull any file from an HTTP(s) server.
To run it, simply do, for instance:
./main https://www.google.com
Here are some raw numbers for you to gauge at. First, compile time.
Orthodox C++
This uses a custom (possbily incorrect) standard library implementation, and uses stdio.h
> time m -B main CC=/bin/cc CXX=/bin/c++
/bin/c++ -g -c -o main.o main.cpp -fno-rtti -fno-exceptions -nostdinc++ -Wall -O3
/bin/cc -s -g -o main main.o -lssl -lcrypto
real 0m0.670s
user 0m0.633s
sys 0m0.037s
C++
This version uses the pure standard C++ library, and uses iostream instead of stdio.h
> time /bin/g++ -s -o main1 main1.cpp -Wall -O3 \
-lssl -lcrypto -static-libstdc++ -fno-rtti -fno-exceptions
real 0m1.280s
user 0m1.094s
sys 0m0.186s
The orthodox version is 1.91x faster than the pure version. What about file size then?
Orthodox C++
> stat main
File: main
Size: 18808 Blocks: 56 IO Block: 4096 regular file
C++
> stat main1
File: main1
Size: 944960 Blocks: 1864 IO Block: 4096 regular file
18808 bytes compared to 944960 bytes. 50x smaller.
So should I do orthodox C++ instead of C++? The answer is, it depends. If you want to write embedded or really small software for C++, then by all means, disable those unnecessary language features and write a custom stdlib. However, if you just want to get things done, then use pure C++. For me, Orthodox C++ is kind of like a middle ground between low and high level C++, just enough to write fast software in, and just enough for it to be safe.