C vs C++
Common things
Order of evaluation of function arguments is unspecified! This code is not guaranteed to print values in any order.
int array[] = {1,2,3,4};
int* ptr = array;
//printf("%d %d %d %d\n", *ptr++, *ptr++, *ptr++, *ptr++);
Differences between modern-ish C and plain C++ standards
Designated initializers for arrays and structures.
Vocabulary:
Aggregate initialization: initialize an aggregate from an initializer list.
Aggregate: is an array or struct / union
Initializer list: a list of elements used to initialize an aggregate, e.g.
{1, 2, 3}
Designated initializer list:
- for structs, it is an initializer list in the form
{ .field_foo = 1, .field_bar = 2 }
- for arrays, it is an initializer list in the form
{ [0] = 1, [1] = 2 }
Note: - designated initializers is a form of aggregate initialization, i.e. initializers of an aggregate type using
{ }
- Added to C++20, but this is still invalid:
- Out of order (
[1] = 123, [0] = 456
)- Nested (
.a.b = ...
)- mixed (designated and not)
char myArray[5] = { [0] = 123, [1] = 456, [2] = 789 };
StructType myStruct = { .foo = 1, .bar = 2 };
Info: https://en.cppreference.com/w/cpp/language/aggregate_initialization#Designated_initializers
Zero Initialization
In an initializer list, all members that are not initialized explicitly are empty-initialized (i.e., set to zero / NULL).
Empty initializer list {}
it's used for zero initialization of arrays.
It is valid in C++ but not in C until C23:
int a[3] = {}; // valid C++ way to zero-out a block-scope array; valid in C since C23
int a[3] = {0}; // valid C and C++ way to zero-out a block-scope array
NOTE for C++ about structures and classes:
You can use struct StructType myStruct = {0}
to zero initialize all fields
in a structure. The effect is same as "aggregate-initialization". All these are
equivalent:
struct MyStruct foo = {};
struct MyStruct foo{};
struct MyStruct foo = MyStruct();
Variable Length Arrays (VLAs) are NOT allowed in C++
void foobar(unsigned int n)
{
unsigned int foo[n];
...
}
String literals must be immutable in C++ (const
)
char* myStr = "foobar"; // valid in C; error in C++
const char* myStr = "foobar"; // valid in C and C++
(Better) idiomatic C++:
auto myStr = "foobar";
Make the pointer itself immutable:
constexpr auto Foo = "bar";
// OR
constexpr const char* Foo = "bar";
Arithmetic on void pointers
Arithmetic on void pointers is allowed in the GNU extension to C, but not in C++ (even in GNU extensions).
void* foo;
foo += 2;
const qualifier
- C++:
const
used on a non-local, non-volatile, non-inline variable gives it internal linkage, unlessextern
is explicitly specified. - C: file-scope
const
variables have external linkage by default.
Overloading and Name Mangling
- C++ supports functions overload, using name mangling.
- C does not support name mangling, so it does not use overload.
You can tell the C++ compiler not to mangle specific part of the code, so that
it will emit object codes with their name un-mangled, using extern "C"
.
This way, you will be able to link this object with C only objects:
Compile with -c
:
// exit reference is un-mangled:
extern "C"
void exit (int __status);
int main(void)
{
exit(0);
return 0;
}
Without extern "C"
:
$ nm a.out
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U _Z4exiti
With extern "C"
:
$ nm a.out
U exit
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main