C のポインター: C プログラミングのポインターとは何ですか? 種類

Cのポインタとは何ですか?

この ポインタ C では、別の変数のアドレスを格納する変数です。 ポインターを使用して、別のポインター関数を参照することもできます。 ポインタはインクリメント/デクリメントでき、つまり次/前のメモリ位置を指すことができます。 ポインタの目的は、メモリ領域を節約し、実行時間を短縮することです。

C でポインターを使用する方法

int 型の変数 v を宣言すると、v は実際に値を格納します。

C でポインターを使用する方法

v は現在ゼロに等しくなります。

ただし、各変数には、値とは別に、そのアドレス (簡単に言うと、メモリ内の場所) もあります。 変数名の前にアンパサンド (&) を付けると、アドレスを取得できます。

C でポインターを使用する方法

変数のアドレスを画面に出力すると、それは完全に乱数のように見えます (さらに、実行ごとに異なる可能性があります)。

Cの例でポインタを使って実際に試してみましょう

C でポインターを使用する方法

このプログラムの出力は -480613588 です。

さて、ポインタとは何でしょうか? ポインタは値を格納する代わりに、変数のアドレスを格納します。


ポインタ変数

Int *y = &v;

変数 ポインター
A に保存 命名 ストレージ/メモリアドレス A 変数 それ ポイント のストレージ/メモリアドレス 別の 変数

ポインタの宣言

変数やポインタと同様に、 Cプログラミング プログラムで使用する前に宣言する必要があります。ポインターは、C の命名規則に従っている限り、任意の名前を付けることができます。ポインター宣言の形式は次のとおりです。

data_type * pointer_variable_name;

ここでは、

  • データ・タイプ C の変数型のポインタの基本型であり、ポインタが指す変数の型を示します。
  • 間接演算子であるアスタリスク(*:乗算に使用されるのと同じアスタリスク)は、ポインターを宣言します。

この C ポインターのチュートリアルで、有効なポインター宣言をいくつか見てみましょう。

int    *ptr_thing;            /* pointer to an integer */ 
int *ptr1,thing;/* ptr1 is a pointer to type integer and thing is an integer variable */
double    *ptr2;    /* pointer to a double */
float    *ptr3;      /* pointer to a float */
char    *ch1 ;       /* pointer to a character */
float  *ptr, variable;/*ptr is a pointer to type float and variable is an ordinary float variable */

ポインタを初期化する

ポインタを宣言した後、標準変数のように変数アドレスを使用して初期化します。C プログラミングのポインタが初期化されていない状態でプログラム内で使用されると、結果は予測不可能になり、悲惨な結果になる可能性があります。

変数のアドレスを取得するには、アドレスが必要な変数の名前の前にアンパサンド (&) 演算子を使用します。ポインターの初期化は次の構文で行われます。

ポインタの構文

 pointer = &variable;

ポインターを説明するための簡単なプログラムを以下に示します。

#include <stdio.h>
int main()
{
   int a=10;    //variable declaration
   int *p;      //pointer variable declaration
   p=&a;        //store address of variable a in pointer p
   printf("Address stored in a variable p is:%x\n",p);  //accessing the address
   printf("Value stored in a variable p is:%d\n",*p);   //accessing the value
   return 0;
}

出力:

Address stored in a variable p is:60ff08
Value stored in a variable p is:10
Operaタ 意味
* 2つの目的に役立ちます

  1. ポインタの宣言
  2. 参照された変数の値を返します
& 目的は 1 つだけ

  • 変数のアドレスを返します

C のポインターの種類

以下は異なる C のポインターの種類:

ヌルポインタ

ポインタ宣言中に null 値を割り当てることで、null ポインタを作成できます。 このメソッドは、ポインタにアドレスが割り当てられていない場合に便利です。 NULL ポインタには常に値 0 が含まれます。

次のプログラムは、ヌル ポインターの使用を示しています。

#include <stdio.h>
int main()
{
	int *p = NULL; 	//null pointer
	printf(“The value inside variable p is:\n%x”,p);
	return 0;
}

出力:

The value inside variable p is:
0

ボイドポインタ

In Cプログラミング、void ポインタはジェネリック ポインタとも呼ばれます。 標準のデータ型はありません。 void ポインターは、キーワード void を使用して作成されます。 任意の変数のアドレスを保存するために使用できます。

次のプログラムは、void ポインターの使用を示しています。

#include <stdio.h>
int main()
{
void *p = NULL; 	//void pointer
printf("The size of pointer is:%d\n",sizeof(p));
return 0;
}

出力:

The size of pointer is:4

ワイルドポインター

ポインタが何も初期化されていない場合、そのポインタはワイルド ポインタと呼ばれます。 これらのタイプの C ポインタは、プログラムに問題を引き起こしたり、プログラムのクラッシュにつながる可能性のある未知のメモリ位置をポイントする可能性があるため、効率的ではありません。 ワイルド ポインタを使用するときは常に注意する必要があります。

次のプログラムはワイルド ポインターの使用を示しています。

#include <stdio.h>
int main()
{
int *p; 	//wild pointer
printf("\n%d",*p);
return 0;
}

出力:

timeout: the monitored command dumped core
sh: line 1: 95298 Segmentation fault      timeout 10s main

「c」の他のタイプのポインターは次のとおりです。

  • ぶら下がりポインタ
  • 複合ポインタ
  • ニアポインタ
  • ファーポインタ
  • 巨大なポインター

直接アクセス ポインターと間接アクセス ポインター

C では、変数コンテンツにアクセスして操作する同等の方法が XNUMX つあります。

  • 直接アクセス: 変数名を直接使用します。
  • 間接アクセス: 変数へのポインタを使用します。

以下のプログラムを使ってこれを理解しましょう

#include <stdio.h>
/* Declare and initialize an int variable */
int var = 1;
/* Declare a pointer to int */
int *ptr;
int main( void )
{
/* Initialize ptr to point to var */
ptr = &var;
/* Access var directly and indirectly */
printf("\nDirect access, var = %d", var);
printf("\nIndirect access, var = %d", *ptr);
/* Display the address of var two ways */
printf("\n\nThe address of var = %d", &var);
printf("\nThe address of var = %d\n", ptr);
/*change the content of var through the pointer*/
*ptr=48;
printf("\nIndirect access, var = %d", *ptr);
return 0;}

エラーなしでプログラムをコンパイルすると、結果は次のようになります。

Direct access, var = 1
Indirect access, var = 1

The address of var = 4202496
The address of var = 4202496

Indirect access, var = 48

C でのポインター演算

ポインタ操作は次の図にまとめられています。

C でのポインター演算
ポインタ Operaン

優先操作(優先順位)

C ポインターを使用する場合は、次の優先順位ルールに従う必要があります。

  • 演算子 * と & は、単項演算子 (否定!、増分 ++、減分 -) と同じ優先順位を持ちます。
  • 同じ式で、単項演算子 *、&、!、++、- は右から左に評価されます。

P ポインタが X 変数を指す場合、* X を記述できる場所であればどこでも P を使用できます。

次の表現は同等です。

int X =10
int *P = &Y;
For the above code, below expressions are true
表現 同等の表現
Y=*P+1

*P=*P+10

*P+=2

++*P

(*P)++

Y=X+1

X=X+10

X+=2

++X

X ++

後者の場合、括弧が必要です。単項演算子 * と ++ は右から左に評価されるため、括弧がないと、ポインター P が増分され、P が指すオブジェクトは増分されません。

以下の表は、Cポインタを扱うときに使用できる算術演算と基本演算を示しています。

Opera生産 説明
譲渡 int *P1,*P2
P1=P2;
P1 と P2 は同じ整数変数を指します
増加と減少 Int *P1;
P1++;P1– ;
オフセット(定数)の追加 これにより、ポインタがテーブル内の N 個の要素を移動できるようになります。
ポインタは、変数の型のバイト数の N 倍だけ増加または減少します。
P1+5;

C ポインタと配列と例

従来はインデックスを使用して配列要素にアクセスしていましたが、ポインタを使用することでこの方法を省略できます。 ポインターを使用すると、配列の各要素に簡単にアクセスできます。

#include <stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};   //array initialization
    int *p;     //pointer declaration
               /*the ptr points to the first element of the array*/

    p=a; /*We can also type simply ptr==&a[0] */
    
    printf("Printing the array elements using pointer\n");
    for(int i=0;i<5;i++)    //loop for traversing array elements
    {
        	printf("\n%x",*p);  //printing array elements
        	p++;    //incrementing to the next element, you can also write p=p+1
    }
    return 0;
}

出力:

1
2
3
4
5

ポインタに特定の数値を追加すると、ポインタの位置は加算演算によって得られた値に移動します。p が現在メモリ位置 0 を指しているポインタであると仮定すると、次の加算演算 p+1 を実行すると、次のように実行されます。

C ポインタと配列

ポインタの加算・インクリメント

p は現在位置 0 を指しているため、1 を加算すると値は 1 になり、ポインタはメモリ位置 1 を指します。

C のポインターと文字列と例

文字列は、null 文字「\ 0」で終わる char オブジェクトの配列です。 ポインタを使用して文字列を操作できます。 C の例のポインタはこのセクションを説明しています

#include <stdio.h>
#include <string.h>
int main()
{
char str[]="Hello Guru99!";
char *p;
p=str;
printf("First character is:%c\n",*p);
p =p+1;
printf("Next character is:%c\n",*p);
printf("Printing all the characters in a string\n");
p=str;  //reset the pointer
for(int i=0;i<strlen(str);i++)
{
printf("%c\n",*p);
p++;
}
return 0;
}

出力:

First character is:H
Next character is:e
Printing all the characters in a string
H
e
l
l
o

G
u
r
u
9
9
!

文字列を処理する別の方法は、次のプログラムのようにポインターの配列を使用することです。

#include <stdio.h>
int main(){
char *materials[ ] = {  "iron",  "copper",  "gold"};
printf("Please remember these materials :\n");
int i ;
for (i = 0; i < 3; i++) {
  printf("%s\n", materials[ i ]);}
  return 0;}

出力:

Please remember these materials:
iron
copper
gold

C のポインターの利点

  • ポインタはメモリ位置にアクセスするのに役立ちます。
  • ポインターは、配列構造の要素にアクセスするための効率的な方法を提供します。
  • ポインタは、動的なメモリ割り当てと割り当て解除に使用されます。
  • ポインタは、リンク リスト、グラフ、ツリーなどの複雑なデータ構造を形成するために使用されます。

C のポインターの欠点

  • ポインタを理解するのは少し複雑です。
  • ポインタは、セグメンテーション違反などのさまざまなエラーを引き起こしたり、まったく必要のないメモリ位置にアクセスしたりする可能性があります。
  • ポインタに不正な値を指定すると、メモリ破損が発生する可能性があります。
  • ポインタもメモリ リークの原因となります。
  • ポインタは変数よりも比較的低速です。
  • プログラマはポインタを操作するのが非常に難しいと感じています。 したがって、ポインタを注意深く操作するのはプログラマの責任です。

まとめ

  • ポインタは、データが保存されるメモリの場所にほかなりません。
  • ポインタはメモリ位置にアクセスするために使用されます。
  • ポインタには、null ポインタ、ワイルド ポインタ、void ポインタ、その他の種類のポインタなど、さまざまな種類があります。
  • ポインタを配列および文字列とともに使用すると、より効率的に要素にアクセスできます。
  • 関数ポインターを作成して関数を動的に呼び出すことができます。
  • 算術演算はポインター上で実行することができ、これをポインター算術と呼びます。
  • ポインターは関数を指すこともでき、ポインターの配列を定義する場合にさまざまな関数を簡単に呼び出すことができます。
  • 異なる変数データ型を扱いたい場合は、型キャスト void ポインタを使用できます。