-1-
The subclauses of this subclause list the differences between C++ and ISO C, by the chapters of this document.
3.1.1 - Clause lex: lexical conventions [diff.lex]
-1- Change: C++ style comments (//) are added
A pair of slashes now introduce a one-line comment.
Rationale:
This style of comments is a useful addition to the language.
Effect on original feature:
Change to semantics of well-defined feature.
A valid ISO C expression containing a division operator followed
immediately by a C-style comment will now be treated as a C++ style
comment.
For example:
{ int a = 4; int b = 8 //* divide by a*/ a; +a; }
-2- Change: New Keywords
New keywords are added to C++;
see lex.key.
Rationale:
These keywords were added in order to implement the new
semantics of C++.
Effect on original feature:
Change to semantics of well-defined feature.
Any ISO C programs that used any of these keywords as identifiers
are not valid C++ programs.
Difficulty of converting:
Syntactic transformation.
Converting one specific program is easy.
Converting a large collection
of related programs takes more work.
How widely used:
Common.
-3- Change: Type of character literal is changed from int to char
Rationale:
This is needed for improved overloaded function argument type
matching.
For example:
It is preferable that this call match the second version of function rather than the first.int function( int i ); int function( char c ); function( 'x' );
will not work the same as C++ programs.sizeof('x') == sizeof(int)
Subclause _lex.string:
-4- Change: String literals made const
The type of a string literal is changed
from ``array of char ''
to ``array of const char.''
The type of a wide string literal is changed
from ``array of wchar_t ''
to ``array of const wchar_t.''
Rationale:
This avoids calling an inappropriate overloaded function,
which might expect to be able to modify its argument.
Effect on original feature:
Change to semantics of well-defined feature.
Difficulty of converting:
Simple syntactic transformation, because string literals
can be converted to
char*;
(conv.array).
The most common cases are handled by a new but deprecated standard
conversion:
char* p = "abc"; //valid in C, deprecated in C++ char* q = expr ? "abc" : "de"; // valid in C, invalid in C++
-1- Change: C++ does not have ``tentative definitions'' as in C
E.g., at file scope,
is valid in C, invalid in C++. This makes it impossible to define mutually referential file-local static objects, if initializers are restricted to the syntactic forms of C. For example,int i; int i;
struct X { int i; struct X *next; }; static struct X a; static struct X b = { 0, &a }; static struct X a = { 1, &b };
-2- Change: A struct is a scope in C++, not in C
Rationale:
Class scope is crucial to C++, and a struct is a class.
Effect on original feature:
Change to semantics of well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
C programs use struct extremely frequently, but the
change is only noticeable when struct, enumeration, or enumerator
names are referred to outside the struct.
The latter is probably rare.
basic.link [also dcl.type]
-3- Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage
Rationale:
Because const objects can be used as compile-time values in
C++, this feature urges programmers to provide explicit initializer
values for each const.
This feature allows the user to put const objects in header files that are included in many compilation units.
Effect on original feature:
Change to semantics of well-defined feature.
Difficulty of converting:
Semantic transformation
How widely used:
Seldom
-4- Change: Main cannot be called recursively and cannot have its address taken
Rationale:
The main function may require special actions.
Effect on original feature:
Deletion of semantically well-defined feature
Difficulty of converting:
Trivial: create an intermediary function such as
mymain(argc, argv).
How widely used:
Seldom
-5- Change: C allows ``compatible types'' in several places, C++ does not
For example,
otherwise-identical struct types with different tag names
are ``compatible'' in C but are distinctly different types
in C++.
Rationale:
Stricter type checking is essential for C++.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
The ``typesafe linkage'' mechanism will find many, but not all,
of such problems.
Those problems not found by typesafe linkage will continue to
function properly,
according to the ``layout compatibility rules'' of this
International Standard.
How widely used:
Common.
-6- Change: Converting void* to a pointer-to-object type requires casting
ISO C will accept this usage of pointer to void being assigned to a pointer to object type. C++ will not.char a[10]; void *b=a; void foo() { char *c=b; }
char *c = (char *) b;
-7- Change: Only pointers to non-const and non-volatile objects may be implicitly converted to void*
Rationale:
This improves type safety.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Could be automated.
A C program containing such an implicit conversion from (e.g.)
pointer-to-const-object to void* will receive a diagnostic message.
The correction is to add an explicit cast.
How widely used:
Seldom.
3.1.3 - Clause expr: expressions [diff.expr]
-1- Change: Implicit declaration of functions is not allowed
Rationale:
The type-safe nature of C++.
Effect on original feature:
Deletion of semantically well-defined feature.
Note: the original feature was labeled as ``obsolescent'' in ISO C.
Difficulty of converting:
Syntactic transformation.
Facilities for producing explicit function declarations are fairly
widespread commercially.
How widely used:
Common.
-2- Change: Types must be declared in declarations, not in expressions
In C, a sizeof expression or cast expression may create a new type.
For example,
declares a new type, struct x .p = (void*)(struct x {int i;} *)0;
stmt.switch, stmt.goto (switch and goto statements)
-1- Change: It is now invalid to jump past a declaration with explicit or implicit initializer (except across entire block not entered)
Rationale:
Constructors used in initializers may allocate
resources which need to be de-allocated upon leaving the
block.
Allowing jump past initializers would require
complicated run-time determination of allocation.
Furthermore, any use of the uninitialized object could be a
disaster.
With this simple compile-time rule, C++ assures that
if an initialized variable is in scope, then it has assuredly been
initialized.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
Seldom.
-2- Change: It is now invalid to return (explicitly or implicitly) from a function which is declared to return a value without actually returning a value
Rationale:
The caller and callee may assume fairly elaborate
return-value mechanisms for the return of class objects.
If
some flow paths execute a return without specifying any value,
the implementation must embody many more complications.
Besides,
promising to return a value of a given type, and then not returning
such a value, has always been recognized to be a questionable
practice, tolerated only because very-old C had no distinction between
void functions and int functions.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
Add an appropriate return value to the source code, e.g. zero.
How widely used:
Seldom.
For several years, many existing C implementations have produced warnings in
this case.
3.1.5 - Clause dcl.dcl: declarations [diff.dcl]
-1- Change: In C++, the static or extern specifiers can only be applied to names of objects or functions
Using these specifiers with type declarations is illegal in C++.
In C, these specifiers are ignored when used on type declarations.
Example:
static struct S { //valid C, invalid in C++ int i; // ... };
-2- Change: A C++ typedef name must be different from any class type name declared in the same scope (except if the typedef is a synonym of the class name with the same name). In C, a typedef name and a struct tag name declared in the same scope can have the same name (because they have different name spaces)
Example:
typedef struct name1 { /*...*/ } name1; //valid C and C++ struct name { /*...*/ }; typedef int name; // valid C, invalid C++
class name { /*...*/ }; name i; //i has type class name
dcl.type [see also basic.link]
-3- Change: const objects must be initialized in C++ but can be left uninitialized in C
Rationale:
A const object cannot be assigned to so it must be initialized
to hold a useful value.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
Seldom.
dcl.type (type specifiers)
-4- Change: Banning implicit int
In C++ a
decl-specifier-seq
must contain a
type-specifier.
In the following example, the
left-hand column presents valid C;
the right-hand column presents
equivalent C++:
void f(const parm); void f(const int parm); const n = 3; const int n = 3; main() int main() /* ... */ /* ... */
-5- Change: C++ objects of enumeration type can only be assigned values of the same enumeration type. In C, objects of enumeration type can be assigned values of any integral type
Example:
enum color { red, blue, green }; color c = 1; //valid C, invalid C++
-6- Change: In C++, the type of an enumerator is its enumeration. In C, the type of an enumerator is int.
Example:
enum e { A }; sizeof(A) == sizeof(int) //in C sizeof(A) == sizeof(e) // in C++ /* and sizeof(int) is not necessary equal to sizeof(e) */
-1- Change: In C++, a function declared with an empty parameter list takes no arguments.
In C, an empty parameter list means that the number and type of the function arguments are unknown"
Example:
int f(); //means int f(void) in C++ // int f(unknown) in C
dcl.fct [see expr.sizeof]
-2- Change: In C++, types may not be defined in return or parameter types. In C, these type definitions are allowed
Example:
void f( struct S { int a; } arg ) {} //valid C, invalid C++ enum E { A, B, C } f() {} // valid C, invalid C++
-3- Change: In C++, the syntax for function definition excludes the ``old-style'' C function. In C, ``old-style'' syntax is allowed, but deprecated as ``obsolescent.''
Rationale:
Prototypes are essential to type safety.
Effect on original feature:
Deletion of semantically well-defined feature.
Difficulty of converting:
Syntactic transformation.
How widely used:
Common in old programs, but already known to be obsolescent.
-4- Change: In C++, when initializing an array of character with a string, the number of characters in the string (including the terminating '\\0') must not exceed the number of elements in the array. In C, an array can be initialized with a string even if the array is not large enough to contain the string terminating '\\0'
Example:
char array[4] = "abcd"; //valid C, invalid C++
class.name [see also dcl.typedef]
-1- Change: In C++, a class declaration introduces the class name into the scope where it is declared and hides any object, function or other declaration of that name in an enclosing scope. In C, an inner scope declaration of a struct tag name never hides the name of an object or function in an outer scope
Example:
int x[99]; void f() { struct x { int a; }; sizeof(x); /* size of the array in C */ /* size of the struct in C++ */ }
-2- Change: In C++, the name of a nested class is local to its enclosing class. In C the name of the nested class belongs to the same scope as the name of the outermost enclosing class
Example:
struct X { struct Y { /* ... */ } y; }; struct Y yy; //valid C, invalid C++
All the definitions of C struct types enclosed in other struct definitions and accessed outside the scope of the enclosing struct could be exported to the scope of the enclosing struct. Note: this is a consequence of the difference in scope rules, which is documented in basic.scope.struct Y; //struct Y and struct X are at the same scope struct X { struct Y { /* ... */ } y; };
-3- Change: In C++, a typedef name may not be redefined in a class declaration after being used in the declaration
Example:
typedef int I; struct S { I i; int I; //valid C, invalid C++ };
class.copy (copying class objects)
-1- Change: Copying volatile objects
The implicitly-declared copy constructor and
implicitly-declared copy assignment operator
cannot make a copy of a volatile lvalue.
For example, the following is valid in ISO C:
struct X { int i; }; struct X x1, x2; volatile struct X x3 = {0}; x1 = x3; //invalid C++ x2 = x3; // also invalid C++
cpp.predefined (predefined names)
-1- Change: Whether __STDC__ is defined and if so, what its value is, are implementation-defined
Rationale:
C++ is not identical to ISO C.
Mandating that __STDC__
be defined would require that translators make an incorrect claim.
Each implementation must choose the behavior that will be most
useful to its marketplace.
Effect on original feature:
Change to semantics of well-defined feature.
Difficulty of converting:
Semantic transformation.
How widely used:
Programs and headers that reference __STDC__ are
quite common.
3.2 - Standard C library [diff.library]
-1- This subclause summarizes the contents of the C++ Standard library included from the Standard C library. It also summarizes the explicit changes in definitions, declarations, or behavior from the ISO/IEC 9899:1990 and ISO/IEC 9899:1990/DAM 1 noted in other subclauses (lib.headers, lib.support.types, lib.c.strings).
-2- The C++ Standard library provides 54 standard macros from the C library, as shown in Table ??.
-3- The header names (enclosed in < and >) indicate that the macro may be defined in more than one header. All such definitions are equivalent (basic.def.odr).
assert | HUGE_VAL | NULL <cstring> | SIGILL | va_arg |
BUFSIZ | LC_ALL | NULL <ctime> | SIGINT | va_end |
CLOCKS_PER_SEC | LC_COLLATE | NULL <cwchar> | SIGSEGV | va_start |
EDOM | LC_CTYPE | offsetof | SIGTERM | WCHAR_MAX |
EOF | LC_MONETARY | RAND_MAX | SIG_DFL | WCHAR_MIN |
ERANGE | LC_NUMERIC | SEEK_CUR | SIG_ERR | WEOF <cwchar> |
errno | LC_TIME | SEEK_END | SIG_IGN | WEOF <cwctype> |
EXIT_FAILURE | L_tmpnam | SEEK_SET | stderr | _IOFBF |
EXIT_SUCCESS | MB_CUR_MAX | setjmp | stdin | _IOLBF |
FILENAME_MAX | NULL <cstddef> | SIGABRT | stdout | _IONBF |
FOPEN_MAX | NULL <cstdio> | SIGFPE | TMP_MAX |
-4- The C++ Standard library provides 45 standard values from the C library, as shown in Table ??:
CHAR_BIT | FLT_DIG | INT_MIN | MB_LEN_MAX |
CHAR_MAX | FLT_EPSILON | LDBL_DIG | SCHAR_MAX |
CHAR_MIN | FLT_MANT_DIG | LDBL_EPSILON | SCHAR_MIN |
DBL_DIG | FLT_MAX | LDBL_MANT_DIG | SHRT_MAX |
DBL_EPSILON | FLT_MAX_10_EXP | LDBL_MAX | SHRT_MIN |
DBL_MANT_DIG | FLT_MAX_EXP | LDBL_MAX_10_EXP | UCHAR_MAX |
DBL_MAX | FLT_MIN | LDBL_MAX_EXP | UINT_MAX |
DBL_MAX_10_EXP | FLT_MIN_10_EXP | LDBL_MIN | ULONG_MAX |
DBL_MAX_EXP | FLT_MIN_EXP | LDBL_MIN_10_EXP | USHRT_MAX |
DBL_MIN | FLT_RADIX | LDBL_MIN_EXP | |
DBL_MIN_10_EXP | FLT_ROUNDS | LONG_MAX | |
DBL_MIN_EXP | INT_MAX | LONG_MIN |
-5- The C++ Standard library provides 19 standard types from the C library, as shown in Table ??:
clock_t | ldiv_t | size_t <cstdio> | wctrans_t |
div_t | mbstate_t | size_t <cstring> | wctype_t |
FILE | ptrdiff_t | size_t <ctime> | wint_t <cwchar> |
fpos_t | sig_atomic_t | time_t | wint_t <cwctype> |
jmp_buf | size_t <cstddef> | va_list |
-6- The C++ Standard library provides 2 standard structures from the C library, as shown in Table ??:
lconv | tm |
-7- The C++ Standard library provides 209 standard functions from the C library, as shown in Table ??:
abort | fmod | isupper | mktime | strftime | wcrtomb |
abs | fopen | iswalnum | modf | strlen | wcscat |
acos | fprintf | iswalpha | perror | strncat | wcschr |
asctime | fputc | iswcntrl | pow | strncmp | wcscmp |
asin | fputs | iswctype | printf | strncpy | wcscoll |
atan | fputwc | iswdigit | putc | strpbrk | wcscpy |
atan2 | fputws | iswgraph | putchar | strrchr | wcscspn |
atexit | fread | iswlower | puts | strspn | wcsftime |
atof | free | iswprint | putwc | strstr | wcslen |
atoi | freopen | iswpunct | putwchar | strtod | wcsncat |
atol | frexp | iswspace | qsort | strtok | wcsncmp |
bsearch | fscanf | iswupper | raise | strtol | wcsncpy |
btowc | fseek | iswxdigit | rand | strtoul | wcspbrk |
calloc | fsetpos | isxdigit | realloc | strxfrm | wcsrchr |
ceil | ftell | labs | remove | swprintf | wcsrtombs |
clearerr | fwide | ldexp | rename | swscanf | wcsspn |
clock | fwprintf | ldiv | rewind | system | wcsstr |
cos | fwrite | localeconv | scanf | tan | wcstod |
cosh | fwscanf | localtime | setbuf | tanh | wcstok |
ctime | getc | log | setlocale | time | wcstol |
difftime | getchar | log10 | setvbuf | tmpfile | wcstombs |
div | getenv | longjmp | signal | tmpnam | wcstoul |
exit | gets | malloc | sin | tolower | wcsxfrm |
exp | getwc | mblen | sinh | toupper | wctob |
fabs | getwchar | mbrlen | sprintf | towctrans | wctomb |
fclose | gmtime | mbrtowc | sqrt | towlower | wctrans |
feof | isalnum | mbsinit | srand | towupper | wctype |
ferror | isalpha | mbsrtowcs | sscanf | ungetc | wmemchr |
fflush | iscntrl | mbstowcs | strcat | ungetwc | wmemcmp |
fgetc | isdigit | mbtowc | strchr | vfprintf | wmemcpy |
fgetpos | isgraph | memchr | strcmp | vfwprintf | wmemmove |
fgets | islower | memcmp | strcoll | vprintf | wmemset |
fgetwc | isprint | memcpy | strcpy | vsprintf | wprintf |
fgetws | ispunct | memmove | strcspn | vswprintf | wscanf |
floor | isspace | memset | strerror | vwprintf |
3.2.1 - Modifications to headers [diff.mods.to.headers]
-1-
For compatibility with the Standard C library,
the C++ Standard library provides the 18
C headers
(depr.c.headers), but their use is deprecated in C++.
3.2.2 - Modifications to definitions [diff.mods.to.definitions]
3.2.2.1 - Type wchar_t [diff.wchar.t]
-1-
wchar_t
is a keyword in this International Standard (lex.key).
It does not appear as a type name defined in any of
<cstddef>,
<cstdlib>,
or
<cwchar>
(lib.c.strings).
3.2.2.2 - Header <iso646.h> [diff.header.iso646.h]
-1-
The tokens
and,
and_eq,
bitand,
bitor,
compl,
not_eq,
not,
or,
or_eq,
xor,
and
xor_eq
are keywords in this International
Standard (lex.key).
They do not appear as macro names defined in
<ciso646>.
3.2.2.3 - Macro NULL [diff.null]
-1-
The macro
NULL,
defined in any of
<clocale>,
<cstddef>,
<cstdio>,
<cstdlib>,
<cstring>,
<ctime>,
or
<cwchar>,
is an implementation-defined C++ null pointer constant in
this International Standard (lib.support.types).
3.2.3 - Modifications to declarations [diff.mods.to.declarations]
-1- Header <cstring>: The following functions have different declarations:
-2-
lib.c.strings describes the changes.
3.2.4 - Modifications to behavior [diff.mods.to.behavior]
-1- Header <cstdlib>: The following functions have different behavior:
-2- Header <csetjmp>: The following functions have different behavior:
-1-
The macro
offsetof,
defined in
<cstddef>,
accepts a restricted set of type arguments in this International Standard.
lib.support.types describes the change.
3.2.4.2 - Memory allocation functions [diff.malloc]
-1- The functions calloc, malloc, and realloc are restricted in this International Standard. lib.c.malloc describes the changes.