再議Cスタイル変数宣言

5840 ワード

NeoRAGEx 2002にはこの問題についての記事がありますが、constや__など、多くの内容が含まれていません.declspec. 最近私はいくつかのこの方面の問題に出会って、1つの系統的な総括をする必要があると感じます.それからいくつかの実験を経て、いくつかの結論を出して、ここでみんなに分かち合います.
Cスタイル変数宣言
Cスタイルの変数宣言、例えば
extern __declspec(dllexport) void(__stdcall * const p[10])(int a, int b);

他の言語とは異なり、ルールは直感的ではなく、なぜ今のようになっているのかを理解するには、まずその考え方を理解する必要があります.最初のCのタイプの書き方は、変数の実際の使用をシミュレートしています.
#include <functional>

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char **argv)
{
    int a[10] = {};
    int a0 = a[0];

    int *p = &a0;
    int p0 = *p;

    int (*f)(int a, int b) = add;
    int result = (*f)(1, 2);
    int result2 = f(1, 2); //          (*f)   f,      ,          

    int g(int a, int b); //    

    auto h = static_cast<int (*)(int a, int b)>(f); //   ,              ,            

    auto i = std::function<int(int a, int b)>(h); //std::function           
    typedef int FuncType(int a, int b);
    auto j = std::function<FuncType>(i); //   typedef              

    return 0;
}

したがって、変数を宣言するには、実際の使い方を書き出してから変数宣言に変換します.たとえば、10個の関数ポインタ要素を含む配列を書きたいです.関数は(int,int)->intで、呼び出しを書くことができます.
int b = (*a[0])(1, 2);

呼び出しから宣言を書く
int (*a[10])(int a, int b);

なお、Cの演算子の優先順位は、まずかっこ、次に右のインデックス[]、関数()、メンバーである.あるいは->それから左の*
Cスタイル変数宣言-const,method const
int add(int a, int b)
{
    return a + b;
}

class A
{
private:
    int a{};
    int b{};
public:
    void foo() const //     const       this const 
    {
        this->a = 0; //    ,this A * const;
        b = 0; //    
        const_cast<A *>(this)->a = 0; //  const_cast this   A *       
    }
};

int main(int argc, char **argv)
{
    //const           const    
    const int a1 = 0;
    int const a2 = 0;

    //const     *  
    const int *a3 = 0;
    int const *a4 = 0;
    a3 = a4; //a3、a4       int   ,         

    //const    *  
    int (* const a5) = 0;
    int * const a6 = 0;
    a5 = a6; //    ,a5    

    //     const          
    int (* const f)(int a, int b) = add;

    //       const          
    void (A::* const g)() const = &A::foo;

    return 0;
}

Cスタイル変数宣言-extern,_declspec, __stdcall等
extern、__declspec(Visual C++)およびいくつかの他のリンクタグは、変数のプロパティであり、一番前に直接追加されます_stdcall(Visual C++)などの呼び出し仕様は、関数の属性であり、関数名の前または関数ポインタの*の前に付けられます.
次の声明の意味がわかります
extern __declspec(dllexport) void(__stdcall * const p[10])(int a, int b);
//  extern __declspec(dllexport)   p
//p      10   ,        void(__stdcall * const)(int a, int b)
//       const     ,          __stdcall
//      (int a, int b),    void