698

C と C++ には多くの違いがあり、すべての有効な C コードが有効な C++ コードであるとは限りません。
(「有効」とは、動作が定義された標準コードを意味します。つまり、実装固有/未定義/などではありません。)

C と C++ の両方で有効なコードが、各言語の標準コンパイラでコンパイルされたときに異なる動作を生成するシナリオはありますか?

それを合理的/有用な比較にするために(質問の明らかな抜け穴を見つけようとするのではなく、実際に役立つことを学ぼうとしています)、次のように仮定しましょう。

  • プリプロセッサに関連するものは何もありません (つまり#ifdef __cplusplus、プラグマなどによるハックはありません)。
  • 実装定義は両方の言語で同じです (例: 数値制限など)。
  • 各標準のかなり最近のバージョンを比較しています (たとえば、C++98 と C90 以降など)
    。バージョンが重要な場合は、それぞれのどのバージョンが異なる動作を生成するかについて言及してください。
4

19 に答える 19

475

C と C++ の関数呼び出しとオブジェクト宣言の違い、および C90 では宣言されていない関数の呼び出しが許可されているという事実を利用する例を次に示します。

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

int f() {
    return printf("hello");
}

C++ では、テンポラリfが作成されて破棄されるため、何も出力されませんが、C90 では、hello宣言されていなくても関数を呼び出すことができるため、出力されます。

名前が 2 回使用されていることを疑問に思っている場合f、C および C++ 標準ではこれが明示的に許可されており、オブジェクトを作成するにはstruct f、構造が必要な場合はあいまいさを解消するように言わなければならず、関数が必要な場合はオフstructにする必要があります。

于 2012-10-15T00:19:04.077 に答える
447

C++ と C90 では、実装で定義されていない異なる動作を取得する方法が少なくとも 1 つあります。C90 には単一行コメントがありません。少し注意すれば、これを使用して、C90 と C++ でまったく異なる結果を持つ式を作成できます。

int a = 10 //* comment */ 2 
        + 3;

C++ では、//行末までがすべてコメントなので、次のようになります。

int a = 10 + 3;

C90 には 1 行のコメントがないため、 のみ/* comment */がコメントです。最初/2はどちらも初期化の一部であるため、次のようになります。

int a = 10 / 2 + 3;

したがって、正しい C++ コンパイラは 13 を返しますが、厳密に正しい C90 コンパイラは 8 を返します。

于 2012-10-15T06:03:47.907 に答える
408

以下は、C および C++ で有効ですが、(ほとんどの場合) iC と C++ で異なる値になります。

int i = sizeof('a');

違いの説明については、C/C++ の文字 ('a') のサイズを参照してください。

この記事の別のもの:

#include <stdio.h>

int  sz = 80;

int main(void)
{
    struct sz { char c; };

    int val = sizeof(sz);      // sizeof(int) in C,
                               // sizeof(struct sz) in C++
    printf("%d\n", val);
    return 0;
}
于 2012-10-14T23:57:11.920 に答える
185

C90 対 C++11 (intdouble):

#include <stdio.h>

int main()
{
  auto j = 1.5;
  printf("%d", (int)sizeof(j));
  return 0;
}

C ではauto、ローカル変数を意味します。C90 では、変数または関数の型を省略しても問題ありません。デフォルトはintです。C++11 ではauto、完全に異なる意味を持ち、初期化に使用された値から変数の型を推測するようコンパイラに指示します。

于 2012-10-15T01:42:35.863 に答える
125

まだ言及されていない別の例で、これはプリプロセッサの違いを強調しています。

#include <stdio.h>
int main()
{
#if true
    printf("true!\n");
#else
    printf("false!\n");
#endif
    return 0;
}

これは、C では "false"、C++ では "true" を出力します - C では、未定義のマクロはすべて 0 に評価されます。C++ では、1 つの例外があります: "true" は 1 に評価されます。

于 2012-10-17T02:17:59.210 に答える
109

C++11 標準ごと:

を。コンマ演算子は、C では左辺値から右辺値への変換を実行しますが、C++ では実行しません。

   char arr[100];
   int s = sizeof(0, arr);       // The comma operator is used.

C++ では、この式の値は 100 になり、C では になりますsizeof(char*)

b. C++ では、列挙子の型は列挙型です。C では、列挙子の型は int です。

   enum E { a, b, c };
   sizeof(a) == sizeof(int);     // In C
   sizeof(a) == sizeof(E);       // In C++

これは、sizeof(int)が と等しくない可能性があることを意味しsizeof(E)ます。

c. C++ では、空の params リストで宣言された関数は引数を取りません。C の空の params リストは、関数の params の数と型が不明であることを意味します。

   int f();           // int f(void) in C++
                      // int f(*unknown*) in C
于 2012-10-15T00:48:45.153 に答える
55

このプログラムは1、C++ と C で出力します0

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int d = (int)(abs(0.6) + 0.5);
    printf("%d", d);
    return 0;
}

これはdouble abs(double)、C++ にオーバーロードがあるために発生しabs(0.6)ます。C では、呼び出す前に double から int への暗黙的な変換が原因で0.6戻りますが、戻ります。C では、 を使用するために を使用する必要があります。0int abs(int)fabsdouble

于 2012-12-15T05:24:07.577 に答える
40
#include <stdio.h>

int main(void)
{
    printf("%d\n", (int)sizeof('a'));
    return 0;
}

C では、これsizeof(int)は、現在のシステムでの の値が何であれ出力します。これは通常、現在4一般的に使用されているほとんどのシステムで使用されます。

C++ では、これは 1 を出力する必要があります。

于 2009-02-23T23:21:55.293 に答える
37

もう 1 つのsizeof落とし穴: ブール式。

#include <stdio.h>
int main() {
    printf("%d\n", (int)sizeof !0);
}

sizeof(int)式の型が であるため、C ではと等しくなりますintが、C++ では通常 1 です (必須ではありませんが)。実際には、ほとんどの場合、それらは異なります。

于 2012-10-15T11:46:00.940 に答える
26

C++ の行末コメントを認識しない、C コンパイラに依存する古い栗...

...
int a = 4 //* */ 2
        +2;
printf("%i\n",a);
...
于 2009-02-24T00:05:11.023 に答える
26

C++ プログラミング言語 (第 3 版)には、次の 3 つの例があります。

  1. @Adam Rosenfieldが述べたように、sizeof( 'a');

  2. //隠しコードを作成するために使用されているコメント:

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. あなたの例のように、アウトスコープに物を隠している構造など。

于 2009-02-24T00:07:37.570 に答える
22

C++ 標準にリストされている別のもの:

#include <stdio.h>

int x[1];
int main(void) {
    struct x { int a[2]; };
    /* size of the array in C */
    /* size of the struct in C++ */
    printf("%d\n", (int)sizeof(x)); 
}
于 2009-02-24T00:28:16.913 に答える
20

C のインライン関数はデフォルトで外部スコープになりますが、C++ のインライン関数はそうではありません。

次の 2 つのファイルを一緒にコンパイルすると、GNU C の場合は "I am inline" が出力されますが、C++ の場合は出力されません。

ファイル 1

#include <stdio.h>

struct fun{};

int main()
{
    fun();  // In C, this calls the inline function from file 2 where as in C++
            // this would create a variable of struct fun
    return 0;
}

ファイル 2

#include <stdio.h>
inline void fun(void)
{
    printf("I am inline\n");
} 

また、C++は、デフォルトである C とは異なり、明示的に宣言されていない限り、すべてのconstグローバルを暗黙的に として扱います。staticexternextern

于 2012-10-15T11:11:09.523 に答える
16
struct abort
{
    int x;
};

int main()
{
    abort();
    return 0;
}

C++ では 0、C では 3 の終了コードで戻ります。

このトリックはおそらくもっと面白いことをするために使用できますが、C に適したコンストラクターを作成する良い方法が思いつきませんでした。かなり移植性のない方法ではありますが、渡されます。

struct exit
{
    int x;
};

int main()
{
    struct exit code;
    code.x=1;

    exit(code);

    return 0;
}

ただし、VC++ 2005 は、「終了コード」がどのように再定義されたかについて不平を言って、C++ モードでのコンパイルを拒否しました。(これはコンパイラのバグだと思います。プログラミングの方法を突然忘れた場合を除きます。)ただし、C としてコンパイルすると、プロセス終了コード 1 で終了しました。

于 2009-02-24T00:11:21.260 に答える
7

C と C++ のグローバル名前空間の違いを忘れないでください。foo.cppがあるとします。

#include <cstdio>

void foo(int r)
{
  printf("I am C++\n");
}

およびfoo2.c

#include <stdio.h>

void foo(int r)
{
  printf("I am C\n");
}

次に、両方とも次のようなmain.cmain.cppがあるとします。

extern void foo(int);

int main(void)
{
  foo(1);
  return 0;
}

C++ としてコンパイルすると、C++ グローバル名前空間のシンボルが使用されます。Cでは、Cのものを使用します:

$ diff main.cpp main.c
$ gcc -o test main.cpp foo.cpp foo2.c
$ ./test 
I am C++
$ gcc -o test main.c foo.cpp foo2.c
$ ./test 
I am C
于 2014-10-17T09:27:43.680 に答える