なぜポインタを使用するのですか?[閉まっている]


356

これは本当に基本的な質問ですが、高級言語でいくつかのプロジェクトをコーディングした後、基本的なC ++プログラミングから始めました。

基本的に私は3つの質問があります:

  1. 通常の変数でポインタを使用する理由
  2. いつ、どこでポインタを使用すればよいですか?
  3. 配列でポインタをどのように使用しますか?

5
以前にこの質問で議論されました願っています!
ダグT.

4
書籍のリストについては、stackoverflow.com / questions / 388242 /…を参照してください。Javaの後、私はAccelerated C ++が非常に便利だと感じました。
Jabba

163
誰かにあなたの家の住所を与えることは、誰にもあなたの家のコピーを与えるよりも簡単なので、私たちはポインタを使用します。
Rishi Dua

14
@RishiDuaこれは、私がこれまでに遭遇したポインターの最も良い説明の1つです。それをありがとう、それは私の理解を深めました:)
Josh

2
ポインターは、複数の値/オブジェクトを返したい場合にも使用できます。
Gaurav 2015年

回答:


172
  • 通常の変数でポインタを使用する理由

短い答えは:しないでください。;-)ポインターは、他に何も使用できない場所で使用されます。これは、適切な機能の欠如、データ型の欠如、または純粋なパフォーマンスのためです。詳細はこちら...

  • いつ、どこでポインタを使用すればよいですか?

ここでの短い答えは、他に何も使用できないところです。Cでは、文字列などの複雑なデータ型をサポートしていません。変数を「参照によって」関数に渡す方法もありません。ここでポインタを使用する必要があります。また、リンクされたリスト、構造体のメンバーなど、事実上すべてを指すようにすることもできます。ただし、ここでは説明しません。

  • 配列でポインタをどのように使用しますか?

少しの努力と多くの混乱で。;-) intやcharなどの単純なデータ型について話す場合、配列とポインタの違いはほとんどありません。これらの宣言は非常に似ています(ただし、同じではありません-たとえば、sizeof異なる値を返します)。

char* a = "Hello";
char a[] = "Hello";

このように配列内の任意の要素に到達できます

printf("Second char is: %c", a[1]);

配列が要素0で始まるため、インデックス1。:-)

または、これを同様に行うことができます

printf("Second char is: %c", *(a+1));

文字を印刷することをprintfに指示しているため、ポインター演算子(*)が必要です。*がない場合、メモリアドレス自体の文字表現が出力されます。今では代わりにキャラクター自体を使用しています。%cの代わりに%sを使用した場合、printfに 'a'が指すメモリアドレスの内容に1を加えたもの(上記の例)を出力するように要求し、*を指定する必要がなかったでしょう。前に:

printf("Second char is: %s", (a+1)); /* WRONG */

しかし、これは2番目の文字を出力するだけではなく、null文字(\ 0)が見つかるまで、次のメモリアドレスのすべての文字を出力します。そして、これは物事が危険になり始めるところです。%sフォーマッタを使用して、charポインタではなく整数型の変数を誤って出力しようとした場合はどうなりますか?

char* a = "Hello";
int b = 120;
printf("Second char is: %s", b);

これにより、メモリアドレス120で見つかったものはすべて印刷され、null文字が見つかるまで印刷されます。このprintfステートメントを実行することは誤りであり、違法ですが、ポインタは実際には多くの環境でint型であるため、おそらくいずれにしても機能します。代わりにsprintf()を使用して、このように長すぎる「char配列」を別の変数に割り当てると、特定の限られたスペースしか割り当てられなかった場合に発生する可能性がある問題を想像してください。おそらく、メモリ内の何かを上書きしてしまい、プログラムがクラッシュする可能性があります(運が良ければ)。

ああ、そしてそれを宣言するときに文字配列値を文字配列/ポインターに割り当てない場合は、値を与える前に十分な量のメモリーを割り当てる必要があります。malloc、callocなどを使用します。これは、配列内の1つの要素/指す単一のメモリアドレスを1つだけ宣言したためです。だからここにいくつかの例があります:

char* x;
/* Allocate 6 bytes of memory for me and point x to the first of them. */
x = (char*) malloc(6);
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* Delete the allocation (reservation) of the memory. */
/* The char pointer x is still pointing to this address in memory though! */
free(x);
/* Same as malloc but here the allocated space is filled with null characters!*/
x = (char *) calloc(6, sizeof(x));
x[0] = 'H';
x[1] = 'e';
x[2] = 'l';
x[3] = 'l';
x[4] = 'o';
x[5] = '\0';
printf("String \"%s\" at address: %d\n", x, x);
/* And delete the allocation again... */
free(x);
/* We can set the size at declaration time as well */
char xx[6];
xx[0] = 'H';
xx[1] = 'e';
xx[2] = 'l';
xx[3] = 'l';
xx[4] = 'o';
xx[5] = '\0';
printf("String \"%s\" at address: %d\n", xx, xx);

割り当てられたメモリのfree()を実行した後でも変数xを使用することはできますが、そこに何があるのか​​はわかりません。また、2番目のメモリの2番目の割り当てが最初のメモリと同じスペースで実行される保証がないため、2つのprintf()が異なるアドレスを与える可能性があることに注意してください。


8
120の例は間違っています。%sではなく%cを使用しているため、バグはありません。小文字のxを出力するだけです。さらに、ポインタがint型であるというその後の主張は誤りであり、ポインタに不慣れなCプログラマに与えるには非常に悪いアドバイスです。
R .. GitHub ICE HELPING ICEの停止

13
-1うまく始めましたが、最初の例は間違っています。いいえ、同じではありません。a前者の場合はポインタであり、後者の場合aは配列です。もう言った?同じではありません!自分で確認してください:sizeof(a)を比較して、新しいアドレスを配列に割り当ててみてください。それは動作しません。
10

42
char* a = "Hello";そして、char a[] = "Hello";同じではありません、彼らはかなり異なっています。1つはポインタを宣言し、もう1つは配列を宣言します。を試してみてsizeof、違いがわかります。
PatrickSchlüter10年

12
「このprintfステートメントを実行することは間違っていたり違法ではありません」。これは明らかに間違っています。そのprintfステートメントには未定義の動作があります。多くの実装では、アクセス違反が発生します。ポインターは、実際にはint型ではなく、実際にはポインターです(他には何もありません)。
マンカルス2011

19
-1、あなたはここで非常に多くの事実を誤りました。私はあなたが賛成票の量や受け入れられた回答ステータスに値しないとだけ言っておきます。
asveikau

50

ポインターを使用する1つの理由は、呼び出された関数で変数またはオブジェクトを変更できるようにするためです。

C ++では、ポインターよりも参照を使用することをお勧めします。参照は基本的にポインタですが、C ++はある程度事実を隠し、値で渡しているように見せかけます。これにより、渡す関数のセマンティクスを変更する必要なく、呼び出し元の関数が値を受け取る方法を簡単に変更できます。

次の例を検討してください。

参照の使用:

public void doSomething()
{
    int i = 10;
    doSomethingElse(i);  // passes i by references since doSomethingElse() receives it
                         // by reference, but the syntax makes it appear as if i is passed
                         // by value
}

public void doSomethingElse(int& i)  // receives i as a reference
{
    cout << i << endl;
}

ポインターの使用:

public void doSomething()
{
    int i = 10;
    doSomethingElse(&i);
}

public void doSomethingElse(int* i)
{
    cout << *i << endl;
}

16
おそらく、null参照を渡すことができないという点で、参照の方が安全であることを言及することをお勧めします。
SpoonMeiser 2008年

26
ええ、それはおそらくリファレンスを使用する最大の利点です。指摘してくれてありがとう。しゃれは意図されていません:)
trshiv 2008年

2
確かにnull参照渡すことができます。nullポインタを渡すのと同じくらい簡単ではありません。
2013年

1
@ n0rdに同意します。null参照を渡すことができないと思うなら、それは間違いです。ダングリング参照を渡す方がnull参照より簡単ですが、最終的にはどちらでも簡単に実行できます。参考資料は、エンジニアが足元を撃たれないように保護する特効薬ではありません。ライブでご覧ください
WhozCraig 2013

2
@ n0rd:これは明示的に未定義の動作です。
Daniel Kamil Kozar、

42
  1. ポインタを使用すると、メモリ内の同じスペースを複数の場所から参照できます。これは、ある場所でメモリを更新でき、その変更をプログラムの別の場所から確認できることを意味します。また、データ構造内のコンポーネントを共有できるため、スペースを節約できます。
  2. ポインタを使用して、アドレスを取得し、メモリ内の特定のスポットに渡す必要があります。ポインタを使用して配列をナビゲートすることもできます。
  3. 配列は、特定のタイプで割り当てられた連続したメモリのブロックです。配列の名前には、配列の開始スポットの値が含まれます。1を追加すると、2番目のスポットに移動します。これにより、配列へのアクセスに使用する明示的なカウンターがなくても、配列を下にスライドするポインターをインクリメントするループを作成できます。

Cの例を次に示します。

char hello[] = "hello";

char *p = hello;

while (*p)
{
    *p += 1; // increase the character by one

    p += 1; // move to the next spot
}

printf(hello);

プリント

ifmmp

これは、各文字の値を受け取り、1ずつ増やすためです。


because it takes the value for each character and increments it by one。アスキーの表現ですか?
Eduardo S.

28

ポインターは、別の変数への間接参照を取得する1つの方法です。変数のを保持する代わりに、変数のアドレスを知らせます。配列の最初の要素(アドレス)へのポインタを使用すると、ポインタを(次のアドレス位置へ)増やすことで次の要素をすばやく見つけることができるため、これは配列を扱うときに特に役立ちます。

私が読んだポインターとポインター演算の最も良い説明は、K&RのThe C Programming Languageにあります。C ++の学習を始めるのに適した本はC ++ Primerです。


1
ありがとうございました!最後に、スタックを使用するメリットの実際的な説明です。配列内の位置へのポインターは、@へのポインターへの相対値にアクセスするパフォーマンスも向上させますか

これはおそらく私が読んだ中で最も良い説明です。人々は物事を「複雑に」する方法を持っています:)
Detilium 2017年

23

これも試してみましょう。

ポインタは参照に似ています。言い換えれば、それらはコピーではなく、元の値を参照する方法です。

何よりもまず、通常ポインターを頻繁に使用する必要があるのは、組み込みハードウェアを扱う場合です。デジタルIOピンの状態を切り替える必要があるかもしれません。割り込みを処理していて、特定の場所に値を格納する必要があるかもしれません。あなたは写真を取得します。ただし、ハードウェアを直接扱っておらず、どのタイプを使用するのか疑問に思っている場合は、このまま読み進めてください。

通常の変数ではなくポインタを使用するのはなぜですか?クラス、構造体、配列などの複雑な型を扱う場合、答えはより明確になります。通常の変数を使用すると、コピーを作成してしまう可能性があります(コンパイラーは状況によってこれを防ぐのに十分賢く、C ++ 11も役立ちますが、今のところその説明は避けます)。

ここで、元の値を変更したい場合はどうなりますか?次のようなものを使用できます。

MyType a; //let's ignore what MyType actually is right now.
a = modify(a); 

これは問題なく機能し、ポインタを使用している理由が正確にわからない場合は、使用しないでください。「おそらくもっと速い」という理由に注意してください。独自のテストを実行し、実際に高速である場合は、それらを使用します。

ただし、メモリを割り当てる必要がある問題を解決しているとします。メモリを割り当てるときは、メモリの割り当てを解除する必要があります。メモリ割り当ては成功する場合と成功しない場合があります。ここでポインタが役に立ちます。これにより、割り当てたオブジェクトの存在をテストしたり、ポインタを逆参照してメモリが割り当てられたオブジェクトにアクセスしたりできます。

MyType *p = NULL; //empty pointer
if(p)
{
    //we never reach here, because the pointer points to nothing
}
//now, let's allocate some memory
p = new MyType[50000];
if(p) //if the memory was allocated, this test will pass
{
    //we can do something with our allocated array
    for(size_t i=0; i!=50000; i++)
    {
        MyType &v = *(p+i); //get a reference to the ith object
        //do something with it
        //...
    }
    delete[] p; //we're done. de-allocate the memory
}

これが、ポインタを使用する理由の鍵です。参照は、参照している要素がすでに存在していることを前提としています。ポインターはしません。

ポインターを使用するもう1つの理由(または少なくともポインターを処理する必要がある)は、ポインターが参照の前に存在していたデータ型だからです。したがって、ライブラリを使用して、自分が得意なことがわかっていることを実行してしまうと、これらのライブラリの多くは、その場所全体でポインタを使用していることがわかります。それらのC ++の前に書かれた)。

ライブラリを使用しなかった場合は、ポインタから遠ざかるようにコードを設計できますが、ポインタが言語の基本的なタイプの1つであることを考えると、より速くそれらを使いこなせるようになればなるほど、あなたのC ++スキルは移植可能です。

保守性の観点から、ポインタを使用する場合は、ポインタの有効性をテストして有効でない場合を処理するか、有効であると仮定して、プログラムは、仮定が破られた場合にクラッシュまたは悪化します。別の言い方をすれば、ポインタの選択は、何かが壊れたときにコードの複雑さを導入するか、メンテナンス作業を増やして、メモリの破損など、ポインタが引き起こすエラーのクラス全体に属するバグを追跡しようとすることです。

したがって、すべてのコードを制御する場合は、ポインタを避け、代わりに参照を使用して、可能な限りそれらをconstに保ちます。これにより、オブジェクトの寿命を考える必要が生じ、コードが理解しやすくなります。

この違いを覚えておいてください。参照は本質的に有効なポインタです。ポインターは常に有効であるとは限りません。

では、無効な参照を作成するのは不可能だと言っているのでしょうか。いいえ。C++ではほとんど何でもできるので、完全に可能です。意図せずに行うのはさらに難しく、意図しないバグの数に驚くでしょう:)


ポインターの使用を本質的に回避できる、メモリマップされたIO用のラッパークラスを作成できます。
einpoklum

13

これは少し異なりますが、Cの多くの機能が理にかなっている理由について洞察に満ちたものです:http : //steve.yegge.googlepages.com/tour-de-babel#C

基本的に、標準のCPUアーキテクチャはフォンノイマンアーキテクチャであり、そのようなマシンでメモリ内のデータ項目の場所を参照し、それを使って計算できると非常に便利です。アセンブリ言語のバリアントを知っている場合は、これが低レベルでどれほど重要であるかがすぐにわかります。

C ++は、ポインタを管理し、「参照」の形でその効果を隠すため、ポインタを少し混乱させます。ストレートCを使用する場合、ポインターの必要性ははるかに明白です。参照による呼び出しを行う他の方法はありません。これは、文字列を格納する最良の方法であり、配列を反復処理する最良の方法です。


12

ポインターの1つの用途(既に他の人の投稿で取り上げられていることについては触れません)は、割り当てられていないメモリにアクセスすることです。これはPCプログラミングにはあまり役に立ちませんが、メモリマッピングされたハードウェアデバイスにアクセスするための組み込みプログラミングで使用されます。

DOSの昔は、ポインタを次のように宣言することで、ビデオカードのビデオメモリに直接アクセスできました。

unsigned char *pVideoMemory = (unsigned char *)0xA0000000;

多くの組み込みデバイスはまだこの手法を使用しています。


ポインターを使用する理由ではありません-スパンのような構造-長さも保持します-ははるかに適切です。最近ですが gsl::span、すぐにそうなりますstd::span
einpoklum

10

ほとんどの場合、ポインタは配列(C / C ++の場合)です。これらはメモリ内のアドレスであり、必要に応じて(「通常」の場合)配列のようにアクセスできます。

それらはアイテムのアドレスなので、小さいです。アドレスのスペースのみを使用します。それらは小さいので、関数に送るのは安価です。そして、それらはその関数がコピーではなく実際のアイテムで機能することを可能にします。

動的ストレージ割り当て(リンクリストなど)を行う場合は、ヒープからメモリを取得する唯一の方法であるため、ポインタを使用する必要があります。


8
ポインタが配列であると言うのは誤解を招くと思います。実際には、配列名は配列の最初の要素へのconstポインターです。配列がそうではないかのように任意のポイントにアクセスできるからといって、アクセス違反が発生する可能性があります:)
rmeador

2
ポインタは配列ではありません。comp.lang.c FAQのセクション6を読んでください
キーストンプソン

ポインタは実際には配列ではありません。また、生の配列でもあまり使用されません-確かにC ++ 11との後ではありませんstd::array
einpoklum

@einpoklum-ポインターは配列に十分に近く、参照演算と配列を反復処理する場合と同等です:) ....また、この回答が2008年に書かれたとき、C ++ 11はリリースから3年後だった
warren

@warren:ポインターは配列でも配列に近いものでもありません。単に配列に減衰するだけです。似ていることを人々に伝えることは教育的に不適切です。また、ポインターと同じ型ではなく、サイズ情報を保持する配列への参照を確実に持つことができます。こちらを
-einpoklum

9

ポインターは、設計が1つの「ノード」を別の「ノード」に効率的にリンクまたはチェーンする機能を必要とする多くのデータ構造で重要です。floatなどの通常のデータ型を指すポインタを「選択」するのではなく、目的が異なるだけです。

ポインタは、高性能やコンパクトなメモリフットプリントが必要な場合に役立ちます。

配列の最初の要素のアドレスをポインターに割り当てることができます。これにより、配下の割り当てられたバイトに直接アクセスできます。ただし、配列の重要な点は、これを行う必要がないようにすることです。


9

変数でポインタを使用する1つの方法は、必要な重複メモリを排除することです。たとえば、大きな複雑なオブジェクトがある場合は、ポインタを使用して、参照ごとにその変数を指すことができます。変数を使用すると、コピーごとにメモリを複製する必要があります。


これが、ポインタではなく参照(または多くても参照ラッパー)を使用する理由です。
einpoklum

6

C ++では、サブタイプpolymorphismを使用する場合、ポインターを使用する必要があります。この投稿を参照してください:ポインターなしのC ++ポリモーフィズム

本当に、あなたがそれについて考えるとき、これは理にかなっています。サブタイプポリモーフィズムを使用する場合、最終的には、実際のクラスがわからないため、どのクラスまたはサブクラスのメソッドの実装が呼び出されるかが事前にわかりません。

不明なクラスのオブジェクトを保持する変数を持つというこの考えは、スタックにオブジェクトを格納するC ++のデフォルト(非ポインター)モードと互換性がありません。このモードでは、割り当てられたスペースの量がクラスに直接対応します。注:クラスに3つではなく5つのインスタンスフィールドがある場合、より多くのスペースを割り当てる必要があります。


'&'を使用して引数を参照渡しする場合、間接参照(つまり、ポインター)が依然として舞台裏で行われていることに注意してください。'&'は、(1)ポインター構文を使用する手間を省く、(2)コンパイラーをより厳密にする(ヌルポインターを禁止するなど)ことができる構文糖衣です。


いいえ、あなたはしていない持っているポインタを使用するために-あなたが参照を使用することができます。そして、「ポインターは舞台裏で関わっている」と書いた場合、それは意味がありません。goto命令は、ターゲットマシンの命令の裏側でも使用されます。私たちはまだそれらを使用することを主張していません。
einpoklum

@ einpoklum-reinstateMonica処理するオブジェクトのセットがあり、各要素を一時変数に割り当て、その変数でポリモーフィックメソッドを呼び出す場合、参照を再バインドできないため、ポインターが必要です。
Sildoreth

派生クラスへの基本クラス参照があり、その参照で仮想メソッドを呼び出すと、派生クラスのオーバーライドが呼び出されます。私が間違っている?
einpoklum

@ einpoklum-reinstateMonicaそうです。ただし、参照されているオブジェクトを変更することはできません。したがって、これらのオブジェクトのリスト/セット/配列をループしている場合、参照変数は機能しません。
Sildoreth

5

場所全体に大きなオブジェクトをコピーすると、時間とメモリが浪費されるためです。


4
そして、ポインタはそれをどのように助けますか?Javaや.Netから来た人はスタックとヒープの違いを知らないので、この答えはほとんど役に立ちません..
Mats Fredriksson

参照渡しできます。それはコピーを防ぎます。
マーティンヨーク

1
@MatsFredriksson-大きなデータ構造を渡して(コピーして)再度結果をコピーするのではなく、RAM内の場所をポイントして、直接変更するだけです。
John U

したがって、大きなオブジェクトをコピーしないでください。そのためのポインタが必要だと誰も言っていません。
einpoklum

5

これが私の答えです。私はエキスパートになるつもりはありませんが、書こうとしているライブラリの1つでポインタが優れていることを発見しました。このライブラリ(OpenGLのグラフィックAPI :-)で、頂点オブジェクトを渡して三角形を作成できます。drawメソッドはこれらの三角形オブジェクトを取得し、私が作成した頂点オブジェクトに基づいてそれらを描画します。大丈夫。

しかし、頂点座標を変更するとどうなりますか?頂点クラスでmoveX()を使用して移動しますか?さて、わかりました。ここで三角形を更新する必要があります。頂点を移動するたびに三角形を更新する必要があるため、メソッドを追加してパフォーマンスを無駄にしています。まだ大したことではありませんが、それほど大きくありません。

さて、大量の頂点と大量の三角形を持つメッシュがあり、メッシュが回転、移動している場合などはどうでしょう。これらの頂点を使用するすべての三角形と、シーン内のすべての三角形を更新する必要があります。これは、どの頂点がどの頂点を使用するのかわからないためです。これは非常にコンピュータに負荷がかかります。風景の上にいくつかのメッシュがある場合、なんてことです!これらの頂点が常に変化しているため、ほぼすべてのフレームですべての三角形を更新しているので、私は困っています!

ポインターを使用すると、三角形を更新する必要はありません。

三角形クラスごとに* Vertexオブジェクトが3つある場合、ジリオンの三角形にはそれ自体が大きい3つの頂点オブジェクトがないため、部屋を節約するだけでなく、これらのポインターは常に、意図されている頂点をポイントします頂点が変化する頻度。ポインターは依然として同じ頂点を指しているため、三角形は変化せず、更新プロセスの処理がより簡単になります。私があなたを混乱させたとしても、私はそれを疑うつもりはありません、私は専門家であるふりをせず、私の2セントを議論に投げ込みます。


4

C言語でのポインターの必要性は、ここで説明されています

基本的な考え方は、言語の多くの制限(配列、文字列の使用、関数での複数の変数の変更など)は、データのメモリ位置を操作することで取り除くことができるということです。これらの制限を克服するために、ポインターがCで導入されました。

さらに、ポインタを使用すると、大きなデータ型(多くのフィールドを持つ構造体など)を関数に渡す場合に、コードをより高速に実行してメモリを節約できることもわかります。渡す前にそのようなデータ型のコピーを作成すると、時間がかかり、メモリを消費します。これが、プログラマーがビッグデータ型のポインターを好むもう1つの理由です。

PS:詳細なサンプルコードの説明については、提供されているリンクを参照してください。


質問はC ++に関するもので、この回答はCに関するものです
。– einpoklum

いいえ、質問にはcおよびc ++のタグが付けられています。おそらくcタグは無関係ですが、最初からここにあります。
ジャン=フランソワ・ファーブル

3

JavaとC#では、すべてのオブジェクト参照はポインターです。c++で重要なのは、ポインターが指す場所をより細かく制御できることです。大きな力には大きな責任が伴います。


1

2番目の質問については、通常、プログラミング中にポインターを使用する必要はありませんが、これには1つの例外があり、それはパブリックAPIを作成する場合です。

人々がポインターを置き換えるために一般的に使用するC ++構成の問題は、使用するツールセットに大きく依存しますが、たとえば、Visual Studio 2008で静的ライブラリをコンパイルする場合は、ソースコードに対して必要なすべてのコントロールがある場合に問題ありません。新しいプロジェクトが後方互換性のない新しいバージョンのSTLにリンクされているため、Visual Studio 2010でそれを使用しようとすると、大量のリンカーエラーが発生します。DLLをコンパイルして別のツールセットで使用するインポートライブラリを提供すると、事態はさらに悪化します。その場合、プログラムは明らかな理由もなく遅かれ早かれクラッシュします。

したがって、あるライブラリから別のライブラリに大きなデータセットを移動する目的で、使用する同じツールを他のユーザーに強制的に使用させたくない場合は、データをコピーするはずの関数への配列へのポインタを与えることを検討できます。 。これについての良い部分は、それがCスタイルの配列である必要さえないということです。例えば、std :: vectorを使用し、最初の要素&vector [0]のアドレスを与えることによってポインターを与えることができます。 std :: vectorは、配列を内部的に管理します。

C ++でポインタを使用するもう1つの理由はライブラリに関連しているため、プログラムの実行時にロードできないdllを用意することを検討してください。インポートライブラリを使用すると、依存関係が満たされず、プログラムがクラッシュします。これは、たとえば、アプリケーションとともにdllでパブリックAPIを提供し、他のアプリケーションからアクセスしたい場合です。この場合、APIを使用するには、DLLをその場所からロードする必要があり(通常はレジストリキーにあります)、DLL内の関数を呼び出せるように関数ポインターを使用する必要があります。APIを作成する人たちは、このプロセスを自動化し、必要なすべての関数ポインターを提供するヘルパー関数を含む.hファイルを提供できるほど優れている場合があります。


1
  • 場合によっては、共有ライブラリ(.DLLまたは.so)にある関数を使用するために関数ポインタが必要になります。これには、多くの場合、DLLインターフェイスが提供されている言語間でのパフォーマンスの実行が含まれます。
  • コンパイラを作る
  • 関数ポインタの配列、ベクトル、または文字列マップがある関数電卓を作成していますか?
  • ビデオメモリを直接変更しようとする-独自のグラフィックパッケージを作成する
  • APIを作ろう!
  • データ構造-作成している特別なツリーのノードリンクポインター

ポインタには多くの理由があります。言語間互換性を維持したい場合は、DLLでC名をマングリングすることが特に重要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.