0

私は、Pythonを少し知っていることから得られる自習のために、「難しい方法でCを学ぶ」ことを行っています。いくつかのチュートリアルを読みましたが、ポインターと割り当てがどのように機能するかについて頭を悩ませることはできません。ポインタを逆参照すると、次のように直接値を指定できることを理解しています。

int *anint = 42;

しかし、すでに作成された変数のメモリ位置を具体的に参照するのはどうでしょうか?具体的には、次のことを試しました。

char *pointer_to_strlit;
char *strlit = "some stuff";
pointer_to_strlit = &strlit;

これを行った後、次の原因でセグメンテーション違反が発生するのはなぜですか。

printf("I print strlit: %s\nI print it again by pointing to it: %s\nI print where the pointer is pointing: %p\n", strlit, *pointer_to_strlit, pointer_to_strlit);

Cの型は、それらがどのように動作するか、およびポインターを使用して特定の型を参照する方法を理解するのが非常に難しいようです。それぞれの異なるデータ型(、、、、、、、、、関数など)を指すための構文を具体的に概説する明確なガイドはありますchar*char?ルールセットを理解するのに役立つステップのリストでさえも役に立ちます。*char[]intstructvoidnull

4

3 に答える 3

2

頑張れ!ポインタは、もっと練習すれば意味があります。しかし、疑問がある場合は、それぞれの値が何を意味するかについて推論してみてください。ペンと紙を使用してメモリ内の各バイトを描画しようとすると、非常に役立ちます。

char *pointer_to_strlit;-ここでは、文字へのポインタを宣言します。ご存知かもしれませんが、Cの文字列は、その文字列の最初の文字へのポインタで表されます。文字列はnullで終了することが期待されます。これは0、文字列が終了したことを示すASCII文字が最終的に存在する必要があることを意味します。

char *strlit = "some stuff";-プログラムのメモリには、この文字列の文字が含まれます(正確には、11文字-表示されるテキストの場合は10文字、ヌルターミネータの場合は1文字)。ここで、別のポインタを宣言します。今回は、その文字列の最初の文字「s」を指します。

pointer_to_strlit = &strlit;-これにより、の値がポインタpointer_to_strlitアドレスにstrlit設定されます。これはおそらくあなたがここで望んでいることではありません。

混乱する場合は、各ポインタを単純な古い数値と考えてみてください。これは基本的にポインタであり、メモリ内のアドレスを表す巨大な数値です。上記をもう一度見てみましょう:

char *pointer_to_strlit;-ここでは、pointer_to_strlitまだ設定していないため、の値は未定義です。

char *strlit = "some stuff";-最初の「s」のアドレスが。であるとしましょう1234500。の値はstrlitその数になり1234500ます。

pointer_to_strlit = &strlit;strlit-しかし、それ自体のアドレスは何ですか?それは他の値です、としましょう1234600。の値はpointer_to_strlitになります1234600

今すぐ印刷pointer_to_strlitしてみて%sください。プログラムがクラッシュします。アドレス1234600は文字列の最初の文字ではなく、別の数字です。巨大な数字のバイトの1つであるポインタです。コードは、nullターミネータを探すために文字列であると見なすものをトラバースしようとし、アクセスできないメモリに到達すると最終的にクラッシュします。

于 2012-07-09T02:21:22.300 に答える
1
int *anint = 42;

42は整数リテラルでありanint、整数自体ではなく整数を指すアドレスを保持することになっています。

char *pointer_to_strlit;
char *strlit = "some stuff";    // Should be const char *strlit = "some stuff";
pointer_to_strlit = &strlit;    // Wrong

&strlitはchar*型であるのに対し、ポインタのアドレス(つまり、char **)を示しますpointer_to_strlit。だから、それはする必要があります

pointer_to_strlit = strlit;

文字列リテラルは読み取り専用の場所にあります。警告をオンにすると、コンパイラは適切なメッセージを表示するはずです。

于 2012-07-09T02:21:59.827 に答える
1
int *anint = 42;

この宣言は正しくありません。 anintはintへのポインタですが、intとして初期化しています。

char *pointer_to_strlit;
char *strlit = "some stuff";

これらの宣言は問題ありません。 "some stuff"は文字列リテラルであり、Cではachar *であるため、初期化strlitしても問題ありません。

pointer_to_strlit = &strlit;

これは正しくありません。 &strlitはのchar**アドレスであるため、char*です。

printf(
    "I print strlit: %s\n"
    "I print it again by pointing to it: %s\n"
    "I print where the pointer is pointing: %p\n", 
    strlit, *pointer_to_strlit, pointer_to_strlit
);

ここでは、として使用strlitしますが%s、これで問題ありません。次に、 *pointer_to_strlitasを使用しますが%s、これは悪いことです。null%sで終了する文字列へのポインタを期待し、charそれにを指定したため、segfaultsになります。

于 2012-07-09T02:28:27.400 に答える