インテル® C++ コンパイラー 17.0 デベロッパー・ガイドおよびリファレンス

コンパイルと実行に関する相違点

インテル® C++ コンパイラーは、Microsoft® Visual C++® コンパイラーと互換性はありますが、相違点もいくつかあり、正常にコンパイルできない場合があります。 また、一部のソースファイルについては、インテル® C++ コンパイラーで互換性のないコードが生成されることがあります。 ほとんどの場合は、ソースファイルを修正すればインテル® C++ コンパイラーでも Microsoft® Visual C++® コンパイラーでも正常にコンパイルできます。 次に、この両者の相違点について説明します。

左シフト演算の評価

インテル® C++ コンパイラーと Microsoft® Visual C++® コンパイラーでは、左シフト演算の評価方法が異なる場合があります。これは、左右のオペランドのサイズをビット単位で比較したときに、右辺のオペランド (つまりシフト桁数) のサイズが左辺のオペランドのサイズ以上の場合です。 ANSI C 標準規格では、このような左シフト演算の動作は不定になっています。つまり、この演算の動作は予測できません。 両コンパイラーで異なる結果が出るのは、このシフト演算の左右のオペランドが定数の場合だけです。 次の例は、インテル® C++ コンパイラーと Microsoft® Visual C++® コンパイラーでの違いについて示したものです。

int x; 
int y = 1; // y を 1 に設定する
void func() {
  x = 1 << 32;
  // インテル® C++ コンパイラーは x を 1 に設定するコードを生成する
  // Visual C++® コンパイラーは x を 0 に設定するコードを生成する  

  y = y << 32;
  // インテル® C++ コンパイラーは y を 1 に設定するコードを生成する
  // Visual C++® コンパイラーは y を 0 に設定するコードを生成する
}

インライン・アセンブリーのターゲットラベル (IA-32 アーキテクチャーのみ)

IA-32 アーキテクチャーを対象にコンパイルする場合、goto 文のインライン・アセンブリー・ターゲット・ラベルは大文字と小文字が区別されます。 Microsoft® Visual C++® コンパイラーは、このようなラベルを扱うときに大文字と小文字を区別しません。 例えば、次のコードをコンパイルするとインテル® C++ コンパイラーからはエラーが発行されます。

int func(int x) {
   goto LAB2;
     // エラー: 定義されていないラベル "LAB2" が参照されている
   __asm lab2: mov x, 1
   return x;
}

しかし、Microsoft® Visual C++® コンパイラーではこのコードを問題なく処理できます。 インテル® C++ コンパイラーを使用する際には、インライン・アセンブリーの中で定義しているラベルを goto 文で参照する場合、そのラベル参照とラベル定義について、名前の大文字と小文字の違いも一致させてください。

dllimport 関数のインライン展開

Microsoft® コンパイラーは dllimport 関数をインライン展開しませんが、インテル® コンパイラーは、dllimport 関数のインライン展開を試みます。 そのため、dllimport ルーチン内で使用される呼び出しと変数がリンク時に 利用できなければなりません。そうでないと、シンボルが未解決になります。

!% cat bug.cpp 

struct Foo2 { 
  static void test(); 
}; 

struct __declspec(dllimport) Foo 
{ 
   void getI() { Foo2::test(); }; 
}; 

struct C  { 
  virtual void test(); 
}; 

void C::test() { Foo* p;  p->getI(); } 

int main() { 
   return 0; 
} 

!% icl -c -w bug.cpp && P:/bin/nm bug.obj | grep Foo2 
Intel® C++ Intel® 64 Compiler for applications running on Intel® 64, Versi 
on 16.0 Beta Build x 
Built Apr  5 2016 12:41:31 by jward4 on JWARD4-DESK1 in D:/workspaces/16_0cfe/de 
v 
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved. 

bug.cpp 
                 U ?test@Foo2@@SAXXZ 
!% cl -c -w bug.cpp && P:/bin/nm bug.obj | grep Foo2 
Microsoft ® C/C++ Optimizing Compiler Version 16.00.40219.01 for x64 
Copyright (C) Microsoft Corporation.  All rights reserved. 

bug.cpp 
!% 

cl で未解決のシンボルは、Foo2::test() ではなく、Foo::getI (メンバー関数)。
Foo::getI は foo.lib で dllexport されるが、Foo2::test はされない。

これは、Foo2::test は Header.h で宣言されており、dllexport/dllimport 修飾子がないため。

#ifndef _HEADER_ 
#define _HEADER_ 
namespace Foo_NS { 

        class Foo2 { 
        public: 
                Foo2(){}; 
                ~Foo2(); 
                static int test(int m_i); 
        }; 
} 
#endif