C elements that are not supported in C++🚫

Read Time:10 Minute, 32 Second

C is a classic language for developing system software and any software for microprocessors. Linux, most of Windows and MacOS are written on it. If you take any modern wearable gadget or electronic device, in most cases they also run under the control of a C program. There is a huge amount of code in the world that is written in C, and more will be written.

C++ is the choice of those who need all the power of C and the flexibility of object-oriented programming at the same time. Counter-Strike, StarCraft, and World of Warcraft are written in C++, which means you can combine the performance of C with modern technology. Part of the Unity engine is also written in C++ to get direct access to system memory and resources.

To briefly describe the difference between these languages, C++ is an improved C. These languages have 99% the same syntax and commands, but C is more about structural and procedural programming, while C++ is about object-oriented.

In this article, I will share a list of C code examples that are not C++ correct or exhibit some C-specific behavior. Note that it is in one direction: C code, which is incorrect from the point of view of C ++.

Of course, the C language has many significant differences from the C++ language, and it will not be difficult for anyone to give examples of incompatibilities based, for example, on keywords or other obvious C99 exclusive features. You won’t find it on this list. My main criterion for choosing examples was that the code should look at first sight “innocent” enough for a C++ observer (i.e., not contain conspicuous C-exclusives), but nevertheless be specific for the C language.

*With [C23], I will mark items that will become irrelevant with the release of C23.

1. In C, it is allowed to “lose” the trailing when initializing a character array with a string literal:

Enter fullscreen mode Exit fullscreen mode

In C++, such initialization is incorrect.

2. C supports tentative definitions. In one translation unit, you can make multiple external definitions of the same object without an initializer:

Enter fullscreen mode Exit fullscreen mode

Such multiple definitions are not allowed in C++.

3. The C language allows the definition of external objects of incomplete types, provided that the type is redefined and becomes complete somewhere further in the same translation unit:

Enter fullscreen mode Exit fullscreen mode

At the level of rationale, this possibility is most likely only a consequence of the previous paragraph, i.e. support for tentative definitions.
The above sequence of declarations is incorrect from the point of view of C++: the C++ language immediately forbids defining objects of incomplete types.

4. In C, you can make a non-defining entity declaration of an incomplete type void.

Enter fullscreen mode Exit fullscreen mode

However, the corresponding definition cannot be made in C because void is an incomplete type.
In C++, you can’t even make a non-defining declaration.

5. The C language allows variables to be defined with the const qualifier without explicit initialization:

Enter fullscreen mode Exit fullscreen mode

In C++, such a definition is incorrect.

6. The C language allows declarations of new types inside the cast operator, inside the sizeof operator, and in function declarations (return types and parameter types):

Enter fullscreen mode Exit fullscreen mode

Such declarations are not allowed in C++.

7. In C, an “unfamiliar” struct type name mentioned in a function’s parameter list is a declaration of a new type local to that function. At the same time, in the list of function parameters, this type can be declared as incomplete, and “additionally declared” to the complete type already in the function body:

Enter fullscreen mode Exit fullscreen mode

In this code, everything is correct from the point of view of the C language: p has the same type as &s and contains the field a.

From the point of view of the C++ language, the mention of an “unfamiliar” class-type name in the list of function parameters is also a declaration of a new type. However, this new type is not local: it is considered to belong to the enclosing namespace. Therefore, from the point of view of the C++ language, the local definition of the type S in the body of the function has nothing to do with the type S mentioned in the parameter list. The assignment p = &s is not possible due to a type mismatch. The above code is incorrect from a C++ point of view.

8. The C language allows transfer of control to the scope of an automatic variable that “jumps” over its initialization declaration:

Enter fullscreen mode Exit fullscreen mode

Such a transfer of control is not allowed from the point of view of C++.

9. Since C99, implicit blocks have appeared in the C language: some statements are themselves blocks and, in addition, induce nested subblocks. For example, the for loop itself is a block, and the loop body is a separate block nested in the for loop block. For this reason, the following code is legal in C:

Enter fullscreen mode Exit fullscreen mode

The variable i declared in the body of the loop has nothing to do with the variable i declared in the head of the loop.

In the C++ language, in such a situation, both the loop header and the loop body form a single scope, which excludes the possibility of a “nested” declaration of i.

10. The C language allows the use of meaningless storage-class specifiers in declarations that do not declare any objects:

Enter fullscreen mode Exit fullscreen mode

This is not allowed in C++.

Additionally, you can notice that in the C language, typedef is also formally just one of the storage-class specifiers, which allows you to create meaningless typedef declarations that do not declare aliases:

Enter fullscreen mode Exit fullscreen mode

C++ does not allow such typedef declarations.

To be fair, such declarations in C are not completely meaningless: they still declare a struct S type.

11. The C language allows explicit repetition of cv-qualifiers in declarations:

Enter fullscreen mode Exit fullscreen mode

The code is incorrect from a C++ point of view. (C++ also turns a blind eye to similar over-qualification, but only through intermediate type names: typedef names, typical template parameters).

12. In C, direct copying of volatile objects is not a problem (at least from the point of view of formal code correctness):

Enter fullscreen mode Exit fullscreen mode

In C++, implicitly generated copy constructors and assignment operators do not take volatile objects as arguments.

13. In C, any integral constant expression with a value 0 can be used as a null pointer constant:

Enter fullscreen mode Exit fullscreen mode

This was also the case in C++ before the adoption of the C++11 standard. However, in modern C++, of integral values, only the literal null value can act as a null pointer constant, but more complex expressions are no longer valid. The above initializations are incorrect from a C++ point of view.

14. The C does not support cv-qualification for rvalues. In particular, the cv-qualification of a function’s return value is immediately ignored by the language. Together with the automatic conversion of arrays to pointers, this allows you to bypass some rules of constant correctness:

Enter fullscreen mode Exit fullscreen mode

It’s worth noting, however, that attempting to modify an rvalue in C results in undefined behavior.

From a C++ perspective, the return value of foo() and hence the array foo().a retains a const-qualification, and implicit conversion of foo().a to type int * is not possible.

15. [C23] The C preprocessor is not familiar with literals such as true and false. In C, true and false are available only as macros defined in the standard header <stdbool.h>. If these macros are not defined, then according to the rules of the preprocessor, both #if true and #if false should behave like #if 0.

At the same time, the C++ preprocessor must naturally recognize true and false literals, and its #if directive must behave in the “expected” way with these literals.

This can be a source of incompatibilities when the C code does not include <stdbool.h>:

Enter fullscreen mode Exit fullscreen mode

This code is obviously incorrect in C++, but at the same time, it can be easily compiled in C.

16. Starting with C++11, the C++ preprocessor no longer treats the <literal><identifier> sequence as independent tokens. From the point of view of the C++ language, <identifier> in this situation is a literal suffix. To avoid this interpretation, in C++ these tokens should be separated by a space:

Enter fullscreen mode Exit fullscreen mode

This format for printf is correct for C, but incorrect from a C++ point of view.

17. Recursive calls of main function are allowed in C, but not in C++. C++ programs are generally not allowed to use the main function in any way.

18. In C, string literals are of type char [N], while in C++ they are const char [N]. Even if “old” C++ supports the conversion of a string literal to type char * as an exception, this exception only works when applied directly to the string literal

Enter fullscreen mode Exit fullscreen mode

Such initialization is incorrect from the point of view of C++.

19. In C, a bit field declared as type int without an explicit indication of signed or unsigned can be either signed or unsigned (this is implementation-defined). In C++, such a bit field is always signed.

20. In C, typedef type names and struct type tags are in different namespaces and do not conflict with each other. For example, such a set of declarations is correct from the point of view of the C:

Enter fullscreen mode Exit fullscreen mode

In C++, there is no separate concept of a tag for class-types: class names share the same namespace with typedef names and may conflict with them. For partial compatibility with C code, C++ allows you to declare typedef aliases that match the names of existing type classes, but only if the alias refers to a type class with exactly the same name. In the above example, the typedef declaration on line 2 is incorrect from a C++ point of view, but the declaration on line 3 is correct.

21. In C, you can use a field name that matches an existing type name.

Enter fullscreen mode Exit fullscreen mode

In C++, such “redefinition” of an identifier is not allowed.

22. In C, an implicit conflict between external and internal linking when declaring the same variable results in undefined behavior, but in C++, such a conflict makes the program ill-formed. To arrange such a conflict, you need to build a rather tricky configuration:

Enter fullscreen mode Exit fullscreen mode

In C++, such an extern declaration is ill-formed. Although there is a separate example in the C++ language standard for this unusual situation, popular C++ compilers generally do not diagnose this violation.

The following are examples of differences that I think are trivial, well-known, and uninteresting.

I include them here for completeness and because they formally satisfy my criterion: at first glance, the code looks more or less normal to the eyes of a C++ observer.

23. The C language allows implicit conversion of pointers from a void * type:

Enter fullscreen mode Exit fullscreen mode

24. In C, values of enum type are implicitly convertible to and from int type:

Enter fullscreen mode Exit fullscreen mode

In C++, implicit conversion only works one way.

25. [C23] The C language supports function declarations without prototypes:

Enter fullscreen mode Exit fullscreen mode

26. In C, nested struct type declarations place the name of the internal type in the external (enclosing) scope:

Enter fullscreen mode Exit fullscreen mode

That, in fact, is all that has accumulated at the moment. I hope you find my observations interesting and they will help someone.
Do you think I missed something important? Feel free to leave any questions, comments, or suggestions.

Source: https://dev.to/mariamarsh/c-elements-that-are-not-supported-in-c-4i6n

Tag Cloud

Java Java Logical Programs OTP Generation in Java python Recursion youtube video ASCII Upper and Lower Case blockchain javascript graph learn to code software development Successful Software Engineers breadth first search Java Array Programs Java Programs Uncategorized android ios programming kotlin web-development django data sql cybersecurity database swiftui serverless aws swift rust react background-position gradients loader mask grid nth-child pseudo elements indieweb WordPress Print Array without brackets C++ factorial Java String Programs Final Keyword Static Variable Axie Infinity Cryptokitties NFT games tool inserting MISC Tips Codes python code python projects python3 system info python project Bigginers How to Do Integrations Payment Gateways PHP checkout page in php Implement stripe payment gateway in Step by step in PHP integrate stripe gatway in php mysql payment gateway integration in php step by step payment gateway integration in php step by step with source code payment gateway integration in website PHP Integrate Stripe Payment Gateway Tutorial PHP shopping cart checkout code shopping cart in php stripe php checkout PHP/MySQL/JSON best international payment gateway does google pay accept international payments how to accept international payments in india paytm payment gateway razorpay codeigniter github razorpay custom checkout github razorpay get payment details razorpay integration in codeigniter github razorpay international payments Razorpay payment gateway integration in CodeIgniter razorpay payment gateway integration in php code Razorpay payment gateway integration with PHP and CodeIgniter Razorpay payment gateway setup in CodeIgniter Library & Frameworks Tips & Tricks UI/UX & Front-end coding birds online html code for google sign in login with google account in PHP login with google account using javascript login with google account using javascript codeigniter login with google account using php login with google account using php source code
Delicious Brains 2022 Year in Review: High-Speed Towards the Future Previous post Delicious Brains 2022 Year in Review: High-Speed Towards the Future
Using Notion as a Headless CMS with Nuxt Next post Using Notion as a Headless CMS with Nuxt

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.