C ++:66 ---非ポータブル機能の特殊なツールや技術(ビット・フィールド、揮発性、にexternリンクのヒント)

  • 基礎となるプログラミングを位置決めするために、C ++は、いくつかの固有の非ポータブルの特性を定義します。いわゆる非ポータブル機器は、異なる特性の特性の結果であります

  • 私たちは別のマシンにあるマシンから据え置き型を含むプログラムする場合、通常、あなたはプログラムを書き換える必要があります算術型サイズは、典型的な例であり、別のマシン上で同じではありません
  • この記事では特性があるについて説明します。
    • ビットフィールド: C言語から派生継承された特性
    • 揮発性: C言語に由来継承特性
    • extern:新しいC ++のリンクが示します

ビットフィールド

  • クラス(非静的)ビットフィールドは、データ・メンバーとして定義されることができるビットの一定量を含むビットフィールドでプログラムが必要とするとき、バイナリデータは、他のプログラムまたはハードウェアデバイスに送信されたときにしばしばビットフィールドを使用し

  • アドレス演算子(&)は、ビットフィールドをスコープすることができず、したがって、ポインタのビットフィールドの任意のタイプを指すことはできません

定義されたビットフィールド

  • ビットフィールドのタイプは、整数または列挙型でなければなりません
  • 符号ビットフィールドと挙動は、特定の実装によって決定されるので、符号なしのタイプは、通常、ビットフィールドを保持しています
  • 結腸と表現の後ろのビットフィールドは、定数式続いて、ビット数を示すために使用される定数式は、メンバーによって占め
  • 例えば:
typedef unsigned int Bit;
class File
{
    Bit mode : 2;       //占2位
    Bit modified : 1;    //占1位  
    Bit prot_owner : 3;  //占3位
    Bit prot_group : 3;  //占3位
    Bit prot_world : 3;  //占3位
public:
    //文件类型以八进制的形式表示
    enum modes { READ = 01, WRITE = 02, EXECUTE = 03 };

    File &open(modes);
    void close();
    void write();
    bool isRead()const;
    void setWrite();
};
  • 圧縮のビットフィールド:
    • 可能な場合は、メモリ圧縮を提供するために、同一の隣接するビット整数でクラス定義連続圧縮内部フィールドビット 
    • 上記のコード例では、5ビットのフィールドは、同じunsigned int型に格納することができます

使用ビットフィールド

  • アクセスは、通常のデータメンバとしてフィールドの道をビット。例えば:
void File::write()
{
    modified = 1;
    //...
}

void File::close()
{
    if (modified)
        //...
}
  •  一般的に内蔵されたビット演算つ以上のビットフィールドを使用:
File &File::open(File::modes m)
{
    mode |= READ; //按默认方式设置READ
    //其他处理
    //如果打开了READ和WRITE
    if (m&WRITE)
        return *this;
}
  • ビットフィールドは、クラスのメンバを定義している場合、それは通常う内またはビットフィールドの値を確認するために関連付けられたメンバー関数のセットを定義します。
inline bool File::isRead()const 
{
    return mode&READ;
}

inline void File::setWrite()
{
    mode |= WRITE;
}

二、揮発性

揮発性の使用シナリオ

  • 直接プログラム処理ハードウェアは、多くの場合、そのような要素を含む直接コントロール以外のプロセス制御プログラムによって、その値を
  • 例えば、プログラムは、定期的にシステムクロックによって更新された変数が含まれていてもよいです。オブジェクトの値がコントロールの外、またはテストを変更することができる場合、オブジェクトは、揮発性として宣言されなければなりません。volatileキーワードは、コンパイラは、このようなオブジェクトのために最適化されてはならない告げます

揮発性変数の定義

  • 以下は、いくつかの揮発性の変数の定義は以下のとおりです。
volatile int display_register; //该int值可能发生改变
volatile Task *curr_task;      //curr_task指向一个volatile对象
volatile int iax[max_size];    //iax的每个元素都是volatile
volatile Screen bitmapBuf;     //bitmapBuf的每个成员都是volatile
  • 揮発性のメンバ関数は揮発性のオブジェクトを呼び出すことができ

揮発性ポインタ

  • 揮発性は、ポインタと一緒に使用することができます
  • 私たちは、揮発性および揮発性のオブジェクトポインタを指して、揮発性のオブジェクトポインタに揮発性のポインタを宣言することができます
  • 例えば:
volatile int v;               //v是一个volatile int
int *volatile vip;            //vip是一个指针,它指向int
volatile int *ivp;            //ivp是一个指针,它指向一个volatile int
volatile int *volatile vivp;  //vivip是一个volatile指针,它指向一个volatile int

//int *ip = &v; 错误,必须使用volatile的指针
ivp = &v;       //正确,ivp是一个指向volatile的指针
vivp = &v;      //正确,vivip是一个指向volatile的volatile指针
  • 同様の規則は、引用した引用は、我々は揮発性のオブジェクトへの参照を使用することができるときにのみとき揮発性の初期化 

揮発性オブジェクトのコピーの合成が無効です

  • 重要な概念:
    • 私たちは、合成に使用することはできません volatileオブジェクトの割り当てからオブジェクトまたは揮発性を初期化するために、コピー/移動コンストラクタと代入演算子を
    • 理由:型合成のメンバーは(不揮発性)const参照をこれを受け入れるパラメータは、明らかに私たちはvolatileオブジェクトへの非揮発性の参照をバインドすることはできません
  • 我々はコピー/移動またはその揮発性オブジェクトを割り当てるのであれば、クラスがコピーまたは移動操作をカスタマイズする必要があります例えば、我々は可能性タイプのパラメータ指定を行う揮発性のconstと呼ばれるので、私たちがコピーできることや割り当て、:
class Foo {
public:
    //从一个volatile对象进行拷贝
    Foo(const volatile Foo&);

    //将一个volatile对象赋值给一个非vaoltile对象
    Foo &operator=(volatile const Foo&);

    //将一个volatile对象赋值给一个vaoltile对象(因为只有volatile对象才能调用这个函数)
    Foo &operator=(volatile const Foo&)volatile;
};
  • 私たちは、揮発性またはコピー代入演算子としてオブジェクトを定義しますが、より深い質問することができますが。どうか、意味のある揮発性のオブジェクトをコピー?実装依存の問題点 

三、EXTERN

  • C ++プログラムは、時には他の言語で書かれた関数を呼び出す必要がある(C言語ベースを)。他のすべての名前と同じように、他の言語での関数名もC ++で宣言する必要があります(と戻り値の型およびパラメータリスト付き)
  • 他の言語で記述された関数については、コンパイラのチェック、それはあなたが通常のC ++を扱う機能が同じであるのと同じ方法を呼び出しますが、生成されるコードは異なりますC ++のリンクは、任意の非尖った言語がC ++の関数を使用示しています

非C ++関数の宣言

  • リンクを示します。
    • 指標は、2つのフォームをリンクすることがあります。シングル、複合体を
    • リンクを示し、クラス定義や関数定義の内部に表示されません
  • 表示形式リンク:
    • externキーワード文字列リテラル+ +シングル/は、関数宣言を設定します
    • リテラル文字列は:コンパイラは、C言語のリンク表示(EXTERN「C」)をサポートする、機能で使用される言語を示し、コンパイラはエイダ、FORTRANや他の言語をサポートすることが可能
  • ケースプレゼンテーション:
//可能出现在C++头文件<cstring>中的链接指示
//单语句的链接指示
extern "C" size_t strlen(const char *);
//可能出现在C++头文件<cstring>中的链接指示
//复合语句的链接指示
extern "C" {
    int strcmp(const char*, const char*);
    char *strcat(char*, const char*);
}

リンクがヘッダファイルを示し、

  • 複合文の形で全体のヘッダ・ファイルに適用することができます例えば、C ++ヘッダファイルは、以下のコードの形のCString有していてもよいです。
//复合语句链接指示
extern "C" {
#include <string.h>  //操作C风格字符串的C函数
}
  • リンク指示を入れ子にすることができ、上記ヘッダーファイルも示す機能へのリンクが含まれている場合、リンカーの機能が影響されません、

ポインタはextern「C」機能

  • その他の見所に書かれた言語の関数ポインタの機能自体は同じリンク命令を使用する必要があります。
  • 例えば:
//pf指向一个C函数,该函数接受一个int返回void
extern "C" void(*pf)(int);
  • 私たちは、現在のコールはCの関数であることを、関数呼び出しPFコンパイラの発見を使用する場合
  • C ++関数をC点にポイントへの関数ポインタは、同じタイプではありません。
    • それは初期化を行うかC ++関数割当動作ポイントされた後に使用することができない関数Cへのポインタを指し
    • そして、その逆
  • 我々がしようとした場合、同じように一致していない問題の他のタイプと同様に2つのポインタの表示との間のリンクに割り当てを行い、それがエラーを生成します。例えば:
void(*pf1)(int);            //指向一个C++函数
extern "C" void(*pf2)(int); //指向一个C函数

pf1 = pf2;                  //错误,pf1和pf2的类型不同

リンク命令は全体の生命のために有効です

  • 我々はリンクを示した場合、それは機能だけでなく、効果的であるが、また、関数ポインタの戻り値の型とパラメータのタイプに対しても有効です。例えば:
//f1是一个C函数,它的形参是一个指向C函数的指针
extern "C" void f1(void(*)(int));
  • 我々は上記の関数f1を呼び出すと、C 関数またはC関数へのポインタに名前を渡す必要があります
  • リンクはそう、宣言文で同時にすべての機能が役割ことを示しているので、我々はC ++関数Cの関数ポインタへのポインタを渡したい場合は、あなたがタイプの別名を使用する必要があります例えば:
//FC是一个指向C函数的指针
extern "C" typedef void FC(int);

//f2是一个C++函数,该函数的形参是指向C函数的指针
void f2(FC *);

他の言語へのエクスポートC ++の機能

  • リンク機能定義された命令を使用することにより、我々は、C ++の関数は、他の言語で書かれたプログラムで使用することができますすることができます例えば:
//calc函数可以被C程序调用
extern "C" double cal(double dparm) {
    //...
}
  • コンパイラは、指定した言語コードのCALC機能を生成します。
  • それは注目に値します。
    • 共有言語はの関数とすることができる多くの制限に戻り値の型やパラメータの型対象
    • 例えば、我々は、C ++クラスは、プログラムCに渡されるオブジェクト入れないことがあり、プログラムCは、コンストラクタ、デストラクタ、および他のクラス固有の操作として理解することができません

オーバーロード機能とリンク命令

  • オーバーロードされた関数は、ターゲット言語に依存したリンクは、相互作用を示しますターゲット言語のサポートが過負荷に機能している場合、関数は、コンパイラのリンクを実現した、それはまた、Cでこれらのオーバーロード関数をサポートすることが示された++

  • Cのリンクのいずれかでオーバーロードされた関数の集合のためにのみ説明を示し理由を理解することは難しいことではありませんので、C言語ではなく、サポート関数のオーバーロードを行います。例えば:

//错误,两个extern "C"函数的名字相同
extern "C" void print(const char*);
extern "C" void print(int);
  • オーバーロードされた関数のセットがある場合には、その後、残りはC ++の関数にバインドされているCの関数は、あります例えば:
class SmallInt {};
class BigNum {};

//C函数可以在C/C++程序中使用
//C++函数重载了该函数,可以在C++程序中调用
extern "C" double calc(double);
extern SmallInt calc(const SmallInt&);
extern BigNum calc(const BigNum&);
  • C関数のバージョンは、CまたはC ++プログラムのCalc呼び出すことができ、およびC ++のクラスの型パラメータの使用は、C ++プログラムを呼び出すことができます。かかわらず、上述した特性のための及び
リリース1504元の記事 ウォンの賞賛1063 ビュー43万+

おすすめ

転載: blog.csdn.net/qq_41453285/article/details/104737491