はじめに
こんにちは 高専一年生メカテック部部員です
以前、ポインタ機能について勉強した際、メモリや変数の型の概念について知りました
かなり理解に苦しんだので、共有したいと思います
あくまで勉強して半年レベルの初心者の捉え方なので、間違いがあると教えていただけると嬉しいです
ポインタの意義
まず、ポインタ変数の必要性や存在意義について説明します
ポインタ変数の仕事
ポインタ変数とは、
アドレスを保存しアドレス元を読み書きすることができるものです
これは主に関数の引数として本領を発揮します
C言語の関数はPythonなどと違い、
戻り値として返すことのできる値は一つのみです
しかしアドレスを保存したポインタ変数を用意すれば
戻り値とは別に変数をその関数内で遠隔操作が可能なのです
ポインタ変数の仕組み
これからは、アドレスの正体やメモリの考え方を説明していきます
覚えなくても問題ないのですが知っておくとより興味を持つことができるので説明します
メモリとは
まず、コンピュータには
「0か1しか保存できないミクロサイズの機器」が並んでいます
その数はまさに膨大であるため無限にあると思っていただいて問題ありません
※実際は有限ですが
あれ?ではなぜ、C言語の変数にはもっと膨大な数値を入れることができるのでしょう?
それは、コンピュータはそれら電子機器を組み合わせ、2進数で様々な数を表しているからです
つまり、int型などは
電子機器をその変数に何個用いるかを決定するのです
アドレスとは
先ほど述べた通り変数ごとに使う電子機器が決まります
しかし
どこの電子機器が使われているのかはコンパイラの気まぐれであるため
プログラマには分からないし分かる必要もありません
しかし考えてみてください
ポインタ変数はアドレスを記憶して元の変数にアクセスします
アドレスは分かりません
だったら使いようがないのではないでしょうか
アドレスの求め方
なんと、変数の頭につけてアドレスをだす素晴らしい記号があります
& です
変数の頭に&をつけるとアドレスが出ます それをもってこのコードをご覧ください
#include <stdio.h>
int main(void)
{
int a;
printf("%d",&a);
return 0;
}
僕の環境では「1375980」と書かれました
ただしこの値はコンパイラや環境によって異なります
このアドレスを保存することではじめてポインタ変数が使えるのです
ポインタ変数の使い方
見本
#include <stdio.h>
int main(void)
{
int a = 0;
int *p;
p = &a;
printf("%d",a);
(*p) ++;
printf("%d",a);
return 0;
}
ポインタ変数の宣言
int *p;
宣言はこれで可能です
int型に必ずすることはありません
ポインタ型とはあくまで型の +α のようなものなのですね
ポインタ変数のアドレスの保存
p = &a;
これで変数aのアドレスを保存しました
ここでは*をポインタ変数につけません
ポインタ変数を使ったアドレス元の変更
(*p) ++;
これで変数aの値を変更しました
ここでは*をポインタ変数につけます
関数にアドレスを引数として渡す際の注意点
#include <stdio.h>
void point(int *p);
int main(void)
{
int a = 0;
printf("%d",a);
point(&a);
printf("%d",a);
return 0;
}
void point(int *p){
(*p) ++;
}
point関数に変数aのアドレスを渡したところまではいいのですが
問題はそれを受け取るポインタ変数部分です
*がついているのにアドレスを保存できているのです
じつは宣言の時に使う*
と、
保存元とアクセスするときにつかう*
は別の役割を担うのです
つまり、偶然point関数の引数部分で宣言しているだけで
*
がついていないことと同じなのです
さいごに
ここまで読んでいただいてありがとうございました
参考にしていただけると嬉しいです
まだ配列ポインタの仕組みの記載を準備中です