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

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 4 页
字号:
  have to share data and code with one another. This section focuses on how to 
  combine C and C++ code in a bilingual system that uses both these languages 
  simultaneously.</p>
<p>The easiest way to ensure compatibility between code modules that are written 
  in C and C++ is to adhere to the common denominator of these languages. Then 
  again, using C++ as a procedural language ("better C") isn't worth the bother 
  -- you can simply stick to C. Combining object-oriented C++ code with procedural 
  C code into a seamless executable is more challenging -- but it offers many 
  advantages.</p>
<h2> <a name="Heading24">C and C++ Linkage Conventions</a></h2>
<p>By default, C++ functions have C++ linkage, which is incompatible with C linkage. 
  Consequently, global C++ functions cannot be called from C code unless they 
  are explicitly declared as having a C linkage.</p>
<h3> <a name="Heading25">Forcing C Linkage on A C++ Function</a></h3>
<p>To override the default C++ linkage, a C++ function has to be declared <tt>extern 
  "C"</tt>.For example</p>
<pre>
<tt>// filename decl.hpp</tt>
<tt><b>extern "C"</b> void f(int n); //force C linkage so that f() can be called from C</tt>
<tt>                          // code although it is compiled by a C++ compiler</tt>
<tt> // decl.hpp</tt>
</pre>
<p>The <tt>extern "C"</tt> prefix instructs a C++ compiler to apply C linkage 
  to the function <tt>f()</tt> rather than the default C++ linkage. This means 
  that a C++ compiler does not apply <i>name mangling</i> to <tt>f()</tt>, either 
  (see the following sidebar, "What's in Name Mangling?"). Consequently, a call 
  to <tt>f()</tt> from C code is properly resolved by a C linker. A C++ linker 
  can also locate the compiled version of <tt>f()</tt> even though it has a C 
  linkage type. In other words, declaring C++ functions as <tt>extern "C"</tt> 
  guarantees interoperability between C++ and C (as well as other procedural languages 
  that use the C calling convention). However, forcing C linkage has a price: 
  It is impossible to overload another version of <tt>f()</tt> that is also declared 
  as <tt>extern "C"</tt>. For example</p>
<pre>
<tt>// filename decl.hpp</tt>
<tt>extern "C" void f(int n);</tt>
<tt>extern "C" void f(float f); //error, second C linkage of f is illegal</tt>
<tt>// decl.hpp</tt>
</pre>
<p>Note that you can declare additional overloaded versions of <tt>f()</tt> as 
  long as they are not declared <tt>extern "C"</tt>:</p>
<pre>
<tt>// filename decl.hpp</tt>
<tt>extern "C" void f(int n); //OK, can be called from C and C++ code</tt>
<tt>void f(float f); //OK, no C linkage used. Can be called only from C++ code</tt>
<tt>void f(char c); //OK, no C linkage used. Can be called only from C++ code</tt>
<tt>// decl.hpp</tt>
</pre>
<p>How does it work? A call to the function from C code is translated to a <cite>CALL</cite> 
  assembly directive, followed by the function name. Declaring a C++ function 
  as <tt>extern "C"</tt> ensures that the name that is generated for it by a C++ 
  compiler is identical to the name that a C compiler expects. On the other hand, 
  if the called function is compiled by a C++ compiler without the <tt>extern 
  "C"</tt> specifier, it has a mangled name but a C compiler still places the 
  nonmangled name after the <tt>CALL</tt> directive, resulting in a link-time 
  error.</p>
<blockquote>
  <hr>
  <b>What's in Name Mangling?<br>
  </b>Name mangling (the more politically correct term, although rarely used, 
  is <i>name decoration</i>) is a method used by a C++ compiler to generate unique 
  names for identifiers in a program. The exact details of the algorithm are compiler-dependent, 
  and they might vary from one version to another. Name mangling ensures that 
  entities with seemingly identical names get unique identifications. The resultant 
  mangled name contains all the information that might be needed by the linker, 
  including linkage type, scope, calling convention, and so on. For instance, 
  when a global function is overloaded, the generated mangled name for each overloaded 
  version is unique. Name mangling is also applied to variables. Thus, a local 
  variable and a global variable with the same user-given name still get distinct 
  mangled names. How is the mangled name synthesized? The compiler picks the user-given 
  name of an identifier and decorates it with additional affixes to indicate a 
  variable of a fundamental type, a class, or a function. For a function, the 
  mangled name embeds its scope and linkage type, the namespace in which it is 
  declared, the list of parameters, the parameters' passing mechanism, and the 
  parameters' cv-qualifications. A mangled name of a member function incorporates 
  additional information such as the class name, whether it is a <tt>const</tt> 
  member function, and other implementation-dependent details that the linker 
  and the runtime environment might need. Following is an example: For a global 
  function <tt>void func(int);</tt>, a given compiler can generate the corresponding 
  mangled name <tt>__x_func@i@</tt>, where the affix <tt>x</tt> indicates a function, 
  <tt>func</tt> is the function's user-given name, <tt>@</tt> indicates the beginning 
  of the parameter list, <tt>i</tt> indicates the type of the parameter, and the 
  closing <tt>@</tt> sign signals the end of the parameter list. An overloaded 
  version of <tt>f()</tt> has a different mangled name because it has a different 
  parameter list. The original user-given name can be reproduced from the mangled 
  name, so linkers in general can issue error messages in a human-readable format. 
  <br>
  <br>
  As was previously stated, the name mangling scheme of a given compiler can change 
  from one version to another (for example, if the new version supports namespaces, 
  whereas the previous one did not). This is one of the reasons you often have 
  to recompile your code with every compiler upgrade. Another important implication 
  is that, usually, the linker and the compiler need to come from the same vendor 
  and have compatible versions. This ensures that they share the same naming conventions 
  and that they produce compatible binary code. 
  <hr>
</blockquote>
<h3> <a name="Heading26">Calling C++ Code from C Code</a></h3>
<p>Up until now, you have observed the C++ side of the story. A C program cannot 
  <tt>#include</tt> the header file <tt>decl.hpp</tt> because the <tt>extern "C"</tt> 
  specifier is not recognized by a C compiler. To ensure that the declaration 
  can be parsed by a C compiler, <tt>extern "C"</tt> needs to be visible to a 
  C++ compiler -- but not to a C compiler. A C++ function with C linkage has to 
  be declared in two distinct forms, one for C++ and another for C. This can be 
  achieved by using separate C and C++ header files. The C header file looks similar 
  to the following:</p>
<pre>
<tt>/*** filename decl.h ***/</tt>
<tt>void f(int n);  /* identical to the C++ header but no extern "C" here */</tt>
<tt> /*** decl.h ***/</tt>
</pre>
<p>The header file can be <tt>#included</tt> in the C source file that calls the 
  function <tt>f()</tt>. For example</p>
<pre>
<tt>/*** filename do_something.c ***/</tt>
<tt>#include "decl.h"</tt>
<tt>void do_something()</tt>
<tt>{</tt>
<tt>  f(5);</tt>
<tt>}</tt>
<tt>/*** do_something.c ***/</tt>
</pre>
<p>Keeping separate header files for C and C++ is not an elegant solution, however. 
  The header files have to remain in sync all the time, and when many header files 
  are used, this can turn into a serious maintenance problem. A better alternative 
  is to use one or more C header files for the declarations. For example</p>
<pre>
<tt>/*** filename f.h ***/</tt>
<tt>void f(int n);  /* identical to the C++ header but no extern "C" here */</tt>
<tt> /*** f.h ***/</tt>
<tt>/*** filename g.h ***/</tt>
<tt>void g(const char * pc, int n);   </tt>
<tt> /*** g.h ***/</tt>
</pre>
<p>Next, the C header files are <tt>#included</tt> in a C++ header file that contains 
  an <tt>extern "C"</tt> block:</p>
<pre>
<tt>// filename decl.hpp</tt>
<tt>extern "C"</tt>
<tt>{</tt>
<tt>#include "f.h"</tt>
<tt>#include "g.h"</tt>
<tt>}</tt>
<tt>// filename decl.hpp</tt>
</pre>
<p>The effect of an <tt>extern "C"</tt> block is as if every declaration in the 
  <tt>#included</tt> header files had a preceding <tt>extern "C"</tt> specifier. 
  Another alternative is to modify the C header file directly by adding an <tt>#ifdef</tt> 
  directive to make the <tt>extern "C"</tt> declaration visible only to a C++ 
  compiler. For example</p>
<pre>
<tt>/*** filename decl.h ***/</tt>
<tt>#ifdef __cplusplus</tt>
<tt>extern "C"  { //visible only to a C++ compiler</tt>
<tt>#endif</tt>
<tt>void g(const char * pc, int n);</tt>
<tt>void f(int n);</tt>
<tt>#ifdef __cplusplus</tt>
<tt>} //visible only to a C++ compiler</tt>
<tt>#endif</tt>
<tt> /*** g.h ***/</tt>
</pre>
<p>This way, only one header file is needed. However, it is not always possible 
  to modify the C header files directly. In such cases, the preceding technique 
  needs to be used. Please note that a C++ function called from C code is an ordinary 
  C++ function. It can instantiate objects, invoke their member functions, or 
  use any other C++ feature. However, some implementations might require special 
  configuration settings to ensure that the linker has access to the C++ libraries 
  and template codes.</p>
<h3> <a name="Heading27">Compiling main()</a></h3>
<p>Functions can be compiled by either a C compiler or a C++ compiler. However, 
  a C++ compiler should compile <tt>main()</tt>. This enables a C++ compiler to 
  take care of templates, static initialization, and additional implementation-dependent 
  operations for which <tt>main()</tt> is responsible. Compiling <tt>main()</tt> 
  under a C compiler will most likely result in link-time errors due to the different 
  semantics of <tt>main()</tt> in C and C++.</p>
<h2> <a name="Heading28">Minimize the Interface Between C and C++ Code</a></h2>
<p>In general, you can call a C function from C++ code without special adjustments. 
  The opposite, as you have seen, is also possible -- but it requires additional 
  adjustments. It is therefore recommended that you keep the interface between 
  the two languages at a minimum. Declaring every C++ function as <tt>extern "C"</tt>, 
  for example, is not recommended. Not only does this convention imply additional 
  modifications to the header files, it also disables overloading. Remember also 
  that you cannot declare a member function <tt>extern "C".</tt> For C++ functions 
  that have to be called from C code, it might be advantageous to use a function 
  wrapper that has an <tt>extern "C"</tt> specifier. In this case, the wrapped 
  C++ functions can have the C++ linkage. For example</p>
<pre>
<tt>void g(const char * pc, int n);  //extern "C" is unnecessary</tt>
<tt>void f(int n);</tt>
<tt>extern "C" void f_Wrapper(int n) //only the wrapper function is called from C</tt>
<tt>{</tt>
<tt>  f(n);</tt>
<tt>}</tt>
<tt>extern "C" void g_Wrapper(const char *pc,  int n)</tt>
<tt>{</tt>
<tt>  g(pc, n);</tt>
<tt>}</tt>
</pre>
<h2> <a name="Heading29">Mixing &lt;iostream&gt; Classes with &lt;stdio.h&gt; 
  Functions</a></h2>
<p>It is possible to use both <tt>&lt;iostream&gt;</tt> classes and <tt>&lt;stdio.h&gt;</tt> 
  library functions in the same program, as long as they do not access the same 
  file. For example, you can use the <tt>&lt;iostream&gt;</tt> object <tt>cin</tt> 
  to read data from the keyboard, and then use <tt>&lt;stdio.h&gt;</tt> functions 
  to write the data to a disk file, as in the following program:</p>
<pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>#include &lt;cstdio&gt;</tt>
<tt>using namespace std;</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  int num;</tt>
<tt>  cin&gt;&gt;num;</tt>
<tt>  cout&lt;&lt;"you enetred: "&lt;&lt; num &lt;&lt;endl;</tt>
<tt>  FILE *fout = fopen("data.dat", "w");</tt>
<tt>  if (fout) //write num to a disk file</tt>
<tt>  {</tt>
<tt>    fprintf(fout, "%d\n", num);</tt>
<tt>  }</tt>
<tt>  fclose(fout);</tt>
<tt>  return 0;</tt>
<tt>}</tt>
</pre>
<p>It is even possible to use <tt>&lt;iostream&gt;</tt> and <tt>&lt;stdio.h&gt;</tt> 
  to manipulate the same file; for instance, a program can send output to both 
  <tt>stdout</tt> and <tt>cout</tt>, although this is not recommended. To enable 
  simultaneous access to the same file, you first have to call <tt>ios::sync_with_stdio(true);</tt> 
  to synchronize the I/O operations. Note, however, that this synchronization 
  degrades performance. Therefore, only use it when <tt>&lt;iostream&gt;</tt> 
  and <tt>&lt;stdio.h&gt;</tt> access the same file. For example</p>
<pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>#include &lt;cstdio&gt;</tt>
<tt>using namespace std;</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  ios::sync_with_stdio(true);//enable mixed I/O</tt>
<tt>  int num;</tt>
<tt>  printf("please enter a number\n");</tt>
<tt>  cin&gt;&gt;num;</tt>
<tt>  cout&lt;&lt;"you enetred: "&lt;&lt; num &lt;&lt; "please enter another one " &lt;&lt; endl;</tt>
<tt>  scanf("%d", &amp;num);</tt>
<tt>  return 0;</tt>
<tt>}</tt>
</pre>
<p>Normally, you won't write such code. However, when a large application combines 
  legacy C functions that use <tt>&lt;stdio.h&gt;</tt> and C++ objects that use 
  <tt>&lt;iostream&gt;</tt>, I/O synchronization is unavoidable because, ultimately, 
  the same low-level system resources are used by both <tt>&lt;stdio.h&gt;</tt> 
  and <tt>&lt;iostream&gt;</tt>.</p>
<p>The fact that <tt>&lt;iostream&gt;</tt> and <tt>&lt;stdio.h&gt;</tt> can be 
  combined is a major advantage. Otherwise, the migration process from C to C++ 
  might be much fussier, and making C and C++ code work together might prove to 
  be very difficult.</p>
<h2> <a name="Heading30">Accessing a C++ Object in C Code</a></h2>
<p>Can C code, which of course is unaware of object semantics, access the data 
  members of a C++ object directly? The short answer is, "Yes, but". There are 
  some guarantees about the underlying memory layout of an object; C code can 
  take advantage of these guarantees and treat a C++ object as an ordinary data 
  struct, provided that all the following restrictions apply to the class of the 
  object in question:</p>
<ul>
  <li>
    <p> The class has no virtual member functions (including inherited virtual 
      functions of a base class).</p>
  </li>
  <p></p>
  <li>
    <p> The class has no virtual base classes in the entire inheritance chain.</p>
  </li>
  <p></p>
  <li>
    <p> The class has no member objects that have either a virtual base class 
      or virtual member functions.</p>
  </li>
  <p></p>
  <li>
    <p> All the data members of the class are declared without an intervening 
      access specifier. </p>
  </li>
</ul>
<p></p>
<h3> <a name="Heading31">The Underlying Representation of an Object in Memory</a></h3>
<p>Examine these restrictions in more detail, given the following declaration 
  of the class <tt>Date</tt>:</p>
<pre>
<tt>class Date</tt>
<tt>{</tt>
<tt>public:</tt>
<tt>  int day;</tt>
<tt>  int month;</tt>

⌨️ 快捷键说明

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