E
The language C is significantly different from that of the C++ from the beginning of its existence. (It is clear that the new features of the C99 language allow us to request examples C of the code that will not be compiled in C++, but in fact, it is not necessary to refer to C99. Even classic standard C-C89/90 is markedly different from C+.)There are great differences, but according to the questioning, we are only interested in the differences that make the C-code correct in C+++. Without claiming completeness, I'll try to list these differences and give examples of the code based on these differences. The key point here is that the syntax designs used are present in both languages, i.e., at first glance the code looks fairly innocent and in terms of C+++.In C, it's allowed to lose '\0' Initiating a set of symbols of stringular literaturechar s[4] = "1234";
The code is incorrect from C+++.C supports "preliminary" definitions. In one broadcast, multiple external definitions of the same object can be made/* На уровне файла */
int a;
int a;
int a, a, a;
The code is incorrect from C+++.In the C typedef-name of types and tags of struct-types located in different domains of names and do not conflict with each other. For example, such a set of announcements is permitted in C struct A { int i; };
typedef struct B { int i; } A;
typedef struct C { int i; } C;
In the C+++ language, there is no separate concept of "thega" for class chips: the names of classes share one area of names with typedef names and can conflict with them. In order to be consistent with the cross-compilable idiomatic code C++, the typedef-pseudonyms matching the names of the existing class-types are permitted, but only if pseudonym refers to the class-type with the same name.In the above example, the first typedef announcement is incorrect in terms of C+++.In "unknown name" struct The type mentioned in the list of performance parameters is the declaration of a new type, local for this function. This type may, however, be declared as incomplete on the list of performance parameters, and the "platted" is already full on the body. /* Тип struct S в этой точке не известен */
void foo(struct S *p)
{
struct S { int a; } s;
p = &s;
p->a = 5;
}
In this code, everything is correct in terms of language p has the same type as &s etc.From the point of view of the C+++ language, the reference to an unmarked name struct The type on the list of performance parameters is also a new type. However, this new type is not local: it is considered to belong to Ext♪ Therefore, from the point of view of C+++, local definition of type S The above example has nothing to do with the type Smentioned on the list of parameters. Switching p = &s Impossible because of non-conformity. The code is incorrect from C+++.C allows definitions of new types inside the activation operator, inside the operator sizeofin the declaration of functions (reset times and parameters) int a = sizeof(enum E { A, B, C }) + (enum X { D, E, F }) 0;
enum E e = B;
int b = e + F;
The code is incorrect from C+++.Language C allows the identification of non-exhaustive objects, provided that the type is predetermined and becomes complete somewhere further in the same unit /* На уровне файла */
struct S s;
struct S { int i; };
The above set of announcements is correct from the point of view of C, but not correct from the point of view of C+++. The C+++ language clearly prohibits the identification of incomplete objects.In C, many statements create their obscure area of visibility, in addition to the already existing area of visibility in the Tele, while C++ creates a single area of visibility.For example for (int i = 0; i < 10; ++i)
{
int i = 42;
}
In C, the body of the cycle is an enlarged area of visibility relative to the heading of the cycle, and this code is therefore correct. In C+++, the visibility area is only one, which precludes the possibility of an occupancy. i♪Language C allows jumps through initialization announcements switch (1)
{
int a = 42;
case 1:;
}
The code is incorrect from C+++.B C Scheduled announcements struct Types place an internal name in the external (covering) visibility area struct A
{
struct B { int b; } a;
};
struct B b;
The code is incorrect from C+++.C allows for non-retroactivity of type indicator void * void *p = 0;
int pp = p;
The code is incorrect from C+++.C supports the announcement of functions without prototypes / На уровне файла */
void foo();
void bar()
{
foo(1, 2, 3);
}
The code is incorrect from C+++.C Type enum freely convertible to type int and back. enum E { A, B, C } e = A;
e = e + 1;
The code is incorrect from C+++.Unidentified C+++ copy designers and acquisition operators cannot copy volatile facilities. B C copy volatile No problemstruct S { int i; };
volatile struct S v = { 0 };
struct S s = v;
The code is incorrect from C+++.B C Structural literature has a type char [N]and in C++- const char [N]♪ Even if you think "Class" C+++ as an exception supports the conversion of string literature to type char *, this exception only works when it is applied directly to the construction literaturechar *p = &"abcd"[0];
The code is incorrect from C+++.C allows the use of unintentional storage class speciators in announcements that do not declare objectsstatic struct S { int i; };
The code is incorrect from C+++.It may be further noted that in C typedef Normally, it is only one of the special features of the storage class that allows for the creation of typedef announcements that do not declare pseudonyms.typedef struct S { int i; };
C++ does not permit such typedef announcements.Permits clear repetition of cv qualification in advertisementsconst const int a = 42;
The code is incorrect in C+++. (C++ allows for a similar " excess " qualification, but only through intermediate names of types: typedef-name, template parameters).In language C, any innumerable constant value 0 may be used as null pointer constantvoid *p = 2 - 2;
void *q = -0;
The same was done in C++ before the adoption of C++11. However, in today ' s C++, only the literal meaning of the calculated values 0 (targeted literal) may act as null pointer constant, but more complex expressions are no longer permissible. The initializations described above are incorrect in terms of C+++.In C, you can make an indefinite announcement of a type object voidextern void v;
(This facility cannot be defined, that is. void Partial type. In C++, it is prohibited to make even an indefinite announcement.In C, the battlefield declared with type int without express signed or unsigned may be labelled and illuminated (defined by implementation). In the C+++ language, this battlefield is always marked.The interpreter of language C is not familiar with literature such as true and false♪ In language C true and false only available as macroes identified in the headline file <stdbool.h>♪ If these macroes are not defined, the Preprocessor ' s rules of work are as follows: #if true and #if false should behave. #if 0♪At the same time, the pre-processor of the C+++ language is obliged to recognize the literature on a proactive basis. true and false and its directive #if I'm sorry, I'm sorry.This may be a source of incompatibility when the C-code does not include <stdbool.h>#if true
int a[-1];
#endif
The code is known to be incorrect in C++, and can at the same time be easily compiled in C.C does not support cv qualification for rvalues. In particular, the cv-qualification of the returning function is ignored by language. In addition to automatically converting the masses to indicator, this allows some rules to be circumventedstruct S { int a[10]; };
const struct S foo() { struct S s; return s; }
int main()
{
int *p = foo().a;
}
From the point of view of C++, returning value foo() and, consequently, the mass foo().a are constant and non-renewable foo().a type int Impossible.In language C, the apparent conflict between internal and external relations, when declaring the same substance, leads to vague behaviour, and in C++, makes a programme of ill-formed (in error). In order to create such an unspeakable conflict, we need to build a pretty shy configuration.static int a;
/ Внутреннее связывание */
void foo(void)
{
int a;
/* Скрывает внешнее static a, не имеет связывания */
{
extern int a;
/* Из-за того, что внешнее static a скрыто, объявляет a
с внешним связыванием. Теперь a объявлено и с внешним,
и с внутренним связыванием - конфликт */
}
}
In C+++, extern- The announcement is wrong.Addressing challenges main permitted in C, but prohibited in C++.Correspondence of C++ is no longer considered (C++11) <строковый или символьный литерал><идентификатор> It's like independent tokens. In terms of C++ <идентификатор> in such a situation is a literary souffix. To avoid such interpretation, in C+++, these tokens should be separated by a gapuint32_t a = 42;
printf("%"PRIu32, a);
This code is correct from the C point of view, but not correct from the C++ point of view.Language C allows for the definition of constant objects without initializationvoid foo()
{
const int a;
}
In C++, such an announcement is incorrect.