⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch13.htm

📁 c++语言操作手册
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"><HTML><HEAD>	<META NAME="Author" Content="Steph Mineart">	<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">	<TITLE>ANSI/ISO C++ Professional Programmer's Handbook - Chapter 13 - C Language Compatibility Issues</TITLE>	<link rel="stylesheet"  TYPE="text/css" href="/includes/stylesheets/ebooks.css"></head><BODY TEXT="#000000" BGCOLOR="#FFFFFF"><CENTER><H1><img src="/publishers/que/series/professional/0789720221/button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>ANSI/ISO C++ Professional Programmer's Handbook</H1></CENTER><CENTER>  <P><A HREF="/publishers/que/series/professional/0789720221/index.htm"><img src="/publishers/que/series/professional/0789720221/button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>   <HR></CENTER><H1 align="center">13</H1><h1 align="center"> C Language Compatibility Issues</h1><address>by Danny Kalev</address><ul>  <li><a href="#Heading1">Introduction</a>   <li><a href="#Heading2">Differences Between ISO C and the C Subset of ANSI/ISO     C++</a>     <ul>      <li><a href="#Heading3">Function Parameter List</a>       <li><a href="#Heading4">Function Declaration</a>       <li><a href="#Heading5">Empty Parameter List</a>       <li><a href="#Heading6">Implicit int Declarations</a>       <li><a href="#Heading7">ISO C is currently being revised to disallow implicit         int declarations.Repeated Declarations of Global Variables</a>       <li><a href="#Heading8">Implicit Casting of void Pointers</a>       <li><a href="#Heading9">The Underlying Representation of NULL Pointers</a>       <li><a href="#Heading10">Default Linkage Type of Global const Variables</a>       <li><a href="#Heading11">Null-Terminated Character Arrays</a>       <li><a href="#Heading12">Assignment of Integers to an enum Type</a>       <li><a href="#Heading13">Definition of Structs in a Function Parameter List         and Return Type</a>       <li><a href="#Heading14">Bypassing an Initialization</a>     </ul>  <li><a href="#Heading15">Quiet Differences Between C and C++</a>     <ul>      <li><a href="#Heading16">The Size of an enum Type</a>       <li><a href="#Heading17">The Size of A Character Constant</a>       <li><a href="#Heading18">Predefined Macros</a>       <li><a href="#Heading19">Default Value Returned from main()</a>     </ul>  <li><a href="#Heading20">Migrating From C to C++</a>     <ul>      <li><a href="#Heading21">Function Wrappers</a>     </ul>  <li><a href="#Heading22">Designing Legacy Code Wrapper Classes</a>   <li><a href="#Heading23">Multilingual Environments</a>   <li><a href="#Heading24">C and C++ Linkage Conventions</a>     <ul>      <li><a href="#Heading25">Forcing C Linkage on A C++ Function</a>       <li><a href="#Heading26">Calling C++ Code from C Code</a>       <li><a href="#Heading27">Compiling main()</a>     </ul>  <li><a href="#Heading28">Minimize the Interface Between C and C++ Code</a>   <li><a href="#Heading29">Mixing &lt;iostream&gt; Classes with &lt;stdio.h&gt;     Functions</a>   <li><a href="#Heading30">Accessing a C++ Object in C Code</a>     <ul>      <li><a href="#Heading31">The Underlying Representation of an Object in Memory</a>       <li><a href="#Heading32">The C++ Object Model is Efficient</a>       <li><a href="#Heading33">Memory Layout of Derived Objects</a>       <li><a href="#Heading34">Support for Virtual Member Functions</a>       <li><a href="#Heading35">Virtual Inheritance</a>       <li><a href="#Heading36">Different Access Specifiers</a>     </ul>  <li><a href="#Heading37">Conclusions</a> </ul><hr size=4><h2> <a name="Heading1">Introduction</a></h2><p>C is a subset of C++. Theoretically, every valid C program is also a valid   C++ program. In practice, however, there are some subtle incompatibilities and   silent differences between the seemingly common portion of both languages. Most   of these differences can be diagnosed by the compiler. Others are more evasive   and, in rare conditions, they can have surprising effects.</p><p>Although it seems that most of the time legacy C code is combined with newer   C++ code, the opposite is also true: C++ code is used in C-based applications.   For example, transaction-processing monitors of relational databases that are   written in C interact with code modules that are written in C++. This chapter   first discusses the differences between ISO C and the C subset of ANSI/ISO C++,   and it demonstrates how to migrate legacy C code to a C++ environment. Next,   you will explore the underlying object model of C++, including the memory layout   of objects, member functions, virtual member functions, virtual base classes,   and access specifiers, and you will learn how C code can access C++ objects. </p><h2> <a name="Heading2">Differences Between ISO C and the C Subset of ANSI/ISO   C++</a></h2><p>With a few minor differences, C++ is a superset of C. The following sections   outline the differences between the C subset of C++ and ISO C. </p><h3> <a name="Heading3">Function Parameter List</a></h3><p>In pre-Standard C, the parameter list of a function was declared as follows:</p><pre><tt>/* pre-standard C, still valid in ISO C, invalid in C++*/</tt><tt>int negate (n)</tt><tt>int n; /* parameter declaration  appears here*/</tt><tt>{</tt><tt>  return -n;</tt><tt>}</tt></pre><p>In other words, only the parameters' names appeared in the parentheses, whereas   their types were declared before the opening brace. Undeclared parameters defaulted   to <tt>int</tt>. In ISO C, as in C++, both the names and types of the parameters   must appear in the parentheses:</p><pre><tt>/* ISO C and C++ */</tt><tt>int negate (int n)</tt><tt>{</tt><tt>  return -n;</tt><tt>}</tt></pre><p>The old-style parameter list is still legal in ISO C, but it is deprecated.   In C++, it is illegal. Legacy C code that contains an old-style parameter list   has to be changed to become valid in C++.</p><h3> <a name="Heading4">Function Declaration</a></h3><p>In C, functions can be called without having to be declared first. In C++,   a function cannot be called without a previous declaration or definition. For   example</p><pre><tt>/* valid in C but not in C++ */</tt><tt>int main()</tt><tt>{</tt><tt>  int n;</tt><tt>  n = negate(5); /* undeclared function; valid in C but not in C++ */</tt><tt>  return 0;</tt><tt>}</tt></pre><p>Functions can be declared in C, just as in C++:</p><pre><tt>/* C/C++ */</tt><tt>int negate(int n);</tt><tt>int main()</tt><tt>{</tt><tt>  int n;</tt><tt>  n= negate(5);</tt><tt>  return 0;</tt><tt>}</tt></pre><p>The use of a function declaration (also called a <i>function prototype</i>)   in C is recommended because it enables the compiler to detect mismatches in   type and argument number. However, it is not a requirement.</p><h3> <a name="Heading5">Empty Parameter List</a></h3><p>In C, a function that is declared with an empty list of parameters such as</p><pre><tt>int f();  </tt><tt>void g( int i)</tt><tt>{</tt><tt>  f(i)  /* valid in C but not in C++ */</tt><tt>}</tt></pre><p>can take any number of arguments of any type. In C++, such a function does   not take any arguments.</p><h3> <a name="Heading6">Implicit int Declarations</a></h3><p>In C and in pre-Standard C++, the default type for missing declarations is   <tt>int</tt>. For example</p><pre><tt>/* valid in C but not in C++ */</tt><tt>void  func()</tt><tt>{</tt><tt>  const k =0; /*int type assumed in C; invalid in C++*/</tt><tt>}</tt></pre><h3> <a name="Heading7">ISO C is currently being revised to disallow implicit   int declarations.Repeated Declarations of Global Variables</a></h3><p>In C, global variables can be declared more than once without the <tt>extern</tt>   specifier. As long as a single initialization (at most) for the same variable   is used, the linker resolves all the repeated declarations into a single entity:</p><pre><tt>/* valid in C but not in C++ */</tt><tt>int flag;</tt><tt>int num;</tt><tt>int flag; /* repeated declaration of a global variable */</tt><tt>void func()</tt><tt>{</tt><tt>  flag = 1;</tt><tt>}</tt></pre><p>In C++, an entity must be defined exactly once. Repeated definitions of the   same entity in separate translation units result in a link-time error. </p><h3> <a name="Heading8">Implicit Casting of void Pointers</a></h3><p>In C, a <tt>void</tt> pointer is implicitly cast to any other pointer type   in assignments and initializations. For example</p><pre><tt>/* valid in C but not C++*/</tt><tt>#include &lt;stdlib.h&gt;</tt><tt>long * p_to_int()</tt><tt>{</tt><tt>  long * pl = malloc(sizeof(long)); /* implicit conversion of void* to long* */</tt><tt>  return pl;</tt><tt>}</tt></pre><p>In general, implicit conversion of <tt>void *</tt> is undesirable because it   can result in bugs that can otherwise be detected by the compiler. Consider   the following example:</p><pre><tt>/* valid in C but not C++*/</tt><tt>#include &lt;stdlib.h&gt;</tt><tt>long * p_to_int()</tt><tt>{</tt><tt>  long * pl = malloc(sizeof(short)); /* oops!  */</tt><tt>  return pl;</tt><tt>}</tt><tt>In C++, void pointers have to be cast explicitly to the desired type. The explicit cast makes the programmer's intention clearer and reduces the likelihood of unpleasant surprises. </tt></pre><h3> <a name="Heading9">The Underlying Representation of NULL Pointers</a></h3><p><tt>NULL</tt> is an implementation-defined <tt>const</tt> null pointer. C implementations   usually define <tt>NULL</tt> as follows:</p><pre><tt> #define NULL  ((void*)0)  </tt></pre><p>However, In C++, <tt>NULL</tt> is usually defined as the literal <tt>0</tt>   (or <tt>0L</tt>), but never as <tt>void *</tt>:</p><pre><tt>const int NULL = 0; //some C++ implementations use this convention</tt><tt>#define NULL 0; //others might use this convention</tt></pre><p>The difference in the underlying representations of <tt>NULL</tt> pointers   between C and C++ derives from the fact that C++ pointers are strongly typed,   whereas in C they are not. If C++ retained C's convention, a C++ statement such   as</p><pre><tt>char * p = NULL;</tt></pre><p>would be expanded into something similar to</p><pre><tt>char * p = (void*) 0;   // compile time error: incompatible pointer types</tt></pre><p>Because <tt>0</tt> is the universal initializer for all pointer types in C++,   it is used instead the traditional C convention; in fact, many programmers simply   use the literal <tt>0</tt> or <tt>0L</tt> instead of <tt>NULL</tt>.</p><h3> <a name="Heading10">Default Linkage Type of Global const Variables</a></h3><p>In C, the default linkage of global <tt>const</tt> variables is <tt>extern</tt>.   An uninitialized <tt>const</tt> variable is implicitly zero initialized. For   example</p><pre><tt>/*** valid in C but not C++ ***/</tt><tt>/* file error_flag.h */</tt><tt>const int error; /*default extern linkage */</tt><tt>/*** end file ***/</tt><tt>#include"error_flag.h"</tt><tt>int func();</tt><tt>int main()</tt><tt>{</tt><tt>  int status = func();</tt><tt>  if( status == error)</tt><tt>  {</tt><tt>    /*do something */</tt><tt>  }</tt><tt>  return 0;</tt><tt>}</tt></pre><p>In C++, a global <tt>const</tt> variable that is not explicitly declared <tt>extern</tt>   has static linkage. In addition, a <tt>const</tt> variable must be initialized.</p><h3> <a name="Heading11">Null-Terminated Character Arrays</a></h3><p>In C, character arrays can be initialized with a string literal without the   null-terminating character. For example</p><pre><tt>/*** valid in C but not C++ ***/</tt><tt>const char message[5] =  "hello"; /* does not contain a null terminator */</tt></pre><p>In C++, character arrays that are initialized by a string literal must be large   enough to contain a null terminator.</p><h3> <a name="Heading12">Assignment of Integers to an enum Type</a></h3><p>In C, the assignment of integers to an enumerated type is valid. For example</p><pre><tt>/*** valid in C but not C++ ***/</tt><tt>enum Status {good, bad};</tt><tt>void func()</tt><tt>{</tt><tt>  Status stat = 1;  /* integer assignment */</tt><tt>}</tt></pre><p>In C++, <tt>enum</tt>s are strongly typed. Only enumerators of the same <tt>enum</tt>   type can be assigned to an <tt>enum</tt> variable. Explicit type casting is   required otherwise. For example</p><pre><tt>//C++</tt><tt>enum Status {good, bad};</tt><tt>void func()</tt><tt>{</tt><tt>  Status stat = static_cast&lt;Status&gt; (1);  // stat = bad</tt><tt>}</tt></pre><h3> <a name="Heading13">Definition of Structs in a Function Parameter List and 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -