6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C言語 ポインタについて

Last updated at Posted at 2017-12-01

最近構造体のポインタについてちょこちょこ聞かれたので、それも含めてポインタについて

ポインタの簡単な説明と
使用例だけ書きます

ポインタとは

アドレスを格納する変数のことです。
プログラムを書く際は、ポインタ変数なるものを宣言して、ある変数のアドレスをそこに格納します。

例えば、
あるint型の変数iのアドレスをint型のポインタ変数pに格納するには…

.c
int i;
int* p;
p = &i;

ポインタ変数は int* pのように書きます。
&アドレス演算子と呼ばれていて、&変数でその変数のアドレスを参照します。
ちなみに値を参照するときは*変数で、*は間接演算子といわれてます。

ちょっと前に書きましたが、ポインタ変数は別の変数のアドレスを格納するものなので以下のコードの出力結果は一緒です。

printf("%p",&i);
printf("%p",p);

使用例

大したことは書けないのですが、こんな感じで使えるよっていうのを例で見てもらえればいいなあと思います。

.c
void func(int* a,int* b){
  *a += 100;
  *b += 200;
}
int main(){
  int i = 10,j = 20;
  int* p1; int* p2;
  // ⇡ int* p1,p2;とかすると
  // p2 はint型になります…

  p1 = &i;
  p2 = &j;

  func(p1,p2);
  // i == 110, j == 220
  func(&i,&j);
  // i == 210, j == 420

  return 0;
}

普通に足せばよくねってツッコミは無しで!

配列

.c
void func(int* a){
  for(int i = 0;i < 10;i++){
    *(a++) = i;
  }
}

int main(){
  int a[20];
  for(int i = 0;i < 20;i++){
    a[i] = 0;
  }
  
  func(a);

  for(int i = 0;i < 20;i++)
    printf("%d, ",a[i]);
  printf("\n");

/* 出力
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
*/
  return 0;
}

実は配列a[x]に関してインデックスを指定せずにaだけやると、a[0]のアドレスが返ってきます。(つまり, a == &a[0])

2017年12月2日追記
a == &a[0]ですが、例外もありますのでこちらのサイト配列→ポインタの読み換えもご覧ください。

なのでfuncの引数にポインタ変数を取って(a++)でアドレスを次へ次へ変えて、変わったアドレスに間接演算子*を用いて配列の値が変えられます。

ポインタ使わなかったらこうです。

void func(int a[]){
  for(int i = 0;i < 10;i++){
    a[i] = i;
  }
}
// mainは同じ

構造体

struct sample{
  int a;
  int b;
};

void func(struct sample* s){
  for(int i = 0;i < 10;i++){
    s->a *= i;
    s->b += i;
  }
}

int main(){
  struct sample s;
  struct sample* sp &= s;

  s.a = 1,s.b = 0;

  func(sp);

  printf("%d\n",s.a);
  printf("%d\n",s.b);
  return 0;
}

構造体とは…

書き終わって構造体わからない人もいるのではと思ったのでざっくり構造体とは…
いろんな型を持てるすごいやつです()

struct 名前{
  int a;
  double b;
  char c;
};

// 上の名前をsampleとすると
int main(){

  struct sample s;
  // s は変数名です。

  s.a // int型
  s.b // double型
  s.c // char型

例みたくいろんな型を持てます。(もちろん配列もOKです)
typedef struct sample dataとか書いてあげると
struct sample 変数名と書かずにdata 変数名で構造体の変数を宣言することができます。

…で、構造体のメンバにアクセスするには上記のように変数名.メンバ名のようにするとアクセスできます。

構造体ポインタ

話をポインタに戻しますが、構造体のポインタからメンバ変数にアクセスするときは
変数名.メンバ名ではなくポインタ変数名->メンバ名という風に書きます。(->はアロー演算子)

typedef struct sample{
  int a;
}data;

int main(){
  data s;
  data* sp;
  s.a = 1;
  sp->a += 1;
// s.a = 2 になります。
}

参考

「配列とポインタの完全制覇」

おわりです

いい例思いつかなくてごめんなさい。

6
10
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?