混在 - CとC++の両方で有効なコードは、各言語でコンパイルすると異なる動作を生成できますか?




visual studio c c++ 混在 (12)

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

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

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

  • プリプロセッサに関連するものはありません( #ifdef __cplusplus 、pragmasなどでハックしないことを意味します)
  • 実装定義されたものは、両方の言語で同じです(数値制限など)
  • 我々は、各標準の合理的に最近のバージョンを比較している(例えば、C ++ 98とC90以降)
    バージョンが重要な場合は、それぞれのバージョンで異なる動作が発生することをご報告ください。

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を返しますが、正しいCコンパイラは8になります。もちろん、ここで任意の数値を選んだだけです。他の数値も使用できます。


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

...
int a = 4 //* */ 2
        +2;
printf("%i\n",a);
...

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はまったく異なるものを意味し、変数の型を初期化に使用した値から推論するようにコンパイラに指示します。


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

#include <stdio.h>

struct f { int x; };

int main() {
    f();
}

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

C ++では、一時的なfが作成されて破棄されるので何も表示されませんが、C90では関数が宣言されていなくてもhelloため、 helloを出力します。

あなたが名前fが2度使われているのか疑問に思っていた場合、CとC ++の標準ではこれを明示的に許可し、 struct fが必要な場合はstruct fと言う必要があります。 。


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

Cのインライン関数は、C ++のインライン関数とは異なり、デフォルトでは外部スコープになります。

次の2つのファイルをまとめてコンパイルすると、GNU Cの場合は "私はインライン"と表示されますが、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 ++はexternがデフォルトであるCとは異なり、 externとして明示的に宣言されていない限り、 constグローバルをstaticとして暗黙的に扱います。


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

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

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

    int f(int a, int b)
    {
        return a //* blah */ b
            ;
    }
    
  3. あなたの例のように構造物などを外に隠すこと。


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

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

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

これは、C ++ではdouble abs(double)オーバーロードがあるために発生します。したがって、 abs(0.6)0.6を返し0が、 int abs(int)を呼び出す前に暗黙的にdouble-to-intに変換するので0返します。 Cでは、 double fabsためにfabsを使用する必要があります。


別のsizeofトラップ:ブール式。

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

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


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

#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と評価されます。


#include <stdio.h>

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

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

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


#include <stdio.h>

struct A {
    double a[32];
};

int main() {
    struct B {
        struct A {
            short a, b;
        } a;
    };
    printf("%d\n", sizeof(struct A));
    return 0;
}

このプログラムは、C ++コンパイラを使用してコンパイルした場合は12832 * sizeof(double) )、Cコンパイラを使用してコンパイルした場合は4します。

これは、Cにはスコープ解決の概念がないためです。 他の構造体に含まれるC構造体では、外部構造体のスコープに入れられます。





c