ポインタ
ポインタとは
「アドレスを格納する変数」のこと。
ポインタは変数であり、変数に格納されているのも数値
ポインタ変数に格納された数値は “アドレス” として扱われる。
ーーーー下記アドレスについての説明ーーーーー
PCは、制御装置、演算装置、記憶装置、入力装置、出力装置に分かれている。
その中で、記憶装置は、プログラムやデータを記憶する装置である。
記憶装置は主記憶装置と、補助記憶装置に分かれる。
主記憶装置(メモリなど)
・動作するために必要なプログラムやデータを一時的に記憶する。
・PCの電源を切ると、その内容は消える。
・CPUから直接アクセスできる記憶装置
・PCやスマホを購入する際に、カタログにメモリサイズが記載されている。
あのメモリサイズは、この主記憶装置を指している。
・コンピュータ処理には、こちらが主に使用される。
補助記憶装置
長期に渡りプログラムやデータを記憶する。
PCの電源を切っても、その内容は消えない。
HDDやSSD、USBメモリなど
アドレスとは
・主記憶装置には、様々なデータが記憶される。
・そのデータを参照するために、一定の区画が用意されている。
・区画ごとに番号が割り振られている。
・メモリ上の区画の位置を示すものをアドレス(又は番地)という。
・基本的には1byteごとに番号が振られ、16進数で表記される。
・アドレスを参照することにより、その中のデータを取得したり、命令を実行したりすることができる。
アドレス空間とは
ハードウェアやソフトウェアから参照し、データの読み出しや書き込みができるメモリ領域のこと。
アドレスとして利用出来るメモリ領域
この領域にデータを書き込んだり、読み込んだりする。
最低限理解すること。
プログラムなどの処理を行う上では、一時的な記憶する主記憶装置(メモリ)が重要になっている。
メモリは、一定区間が用意されており、そこに番号が付いている。
その中でも、データの読み書きが出来る所がアドレス空間という。
この番号(アドレス、番地)を使って、メモリにアクセスする。
参考サイト:
https://daeudaeu.com/pointer/
https://atmarkit.itmedia.co.jp/icd/root/52/5784552.html
https://www.foresight.jp/fe/column/main-memory/
https://tmytokai.github.io/open-ed/activity/c-pointer/text01/page05.html
https://xtech.nikkei.com/it/pc/article/NPC/20061110/253260/#:~:text=64ビットWindowsの場合,空間は8TBに及ぶ%E3%80%82
参考本:
キタミ式イラストIT塾
下の図は一番左上のマスを 0 番地とした例で、青マスは 24 番地にあることを示したものになります。
https://gyazo.com/2e647a97299646fd6e9643a78a4932c5
メモリが 1GB あるのであれば、1024 * 1024 * 1024 個のマスがあり、それぞれにアドレスが割り振られることになる。
そのアドレスから、メモリ上の位置が特定できるようになっている。
例:
変数 A と変数 B の変数宣言を行う。
code:c
char A;
int B;
その場合、下記のように変数AとBのアドレスが配置される。
この場合だと、Aは12番地、Bは16番地に配置された。
この 12 番地、16 番地のようなメモリ空間上の位置をアドレスと呼ぶ。
https://gyazo.com/84c70488fce597370a51af0c9563d760
アドレスは 16 進数で表現することが多い。
ここではアドレスは 10 進数で表現して説明する。
基本的にプログラムで扱うデータ(変数など)は全てメモリ上に配置されている。
アドレス観点から考えた時の変数への処理
変数への値の代入:その変数が配置されたアドレスに値を格納する
変数からの値の取得:その変数が配置されたアドレスから値を取得する
例:
code:c
char A;
int B;
A= 'K';
メモリに値が格納される。
https://gyazo.com/c6046c2ab849f9c1f66c5c825dc35afa
アドレスの取得方法:
C言語では「変数名の前に & 記号をつける」ことで、変数のアドレスを取得する。
& はアドレス演算子と呼ぶ。
例:
code:c
int x;
printf("x's address : %p\n", &x);
printf でアドレスを表示する際には、書式指定子には %p を用いる。
16 進数でアドレスが表示される。
ブラウザで確認:https://paiza.io/projects/4A2dN0thUh1ASLv6Mek9og
https://gyazo.com/67d454c334edd526b3485fa656237e58
まとめ
アドレスは「メモリ上の位置」を示す値
プログラムを実行すると変数はメモリ上に配置され、アドレスが割り振られる
配置される場所は「自分のプログラム用のメモリ」の中
変数のアドレスはアドレス演算子 & により取得できる
ーーーーアドレスの説明終了ーーーーーーー
ーーーーポインタの説明ーーーーーーーー
ポインタとは
「アドレスを格納する変数」のこと。
ポインタのメリット
できることが増える
高速化が出来る
省メモリ化出来る
ポインタを利用する:
利用する場合は他の変数同様に変数宣言が必要
宣言方法:
変数名の前に * をつけて変数宣言を行う。
その変数はプログラム内でポインタとして扱われます。
例:
code:c
char x; //通常の変数
char y; //通常の変数
char *ptr; //ポインタ変数
ポインタで重要なこと
「何を(どこを)指しているか」
ポインタには、メモリ空間のアドレスが格納されている。
アドレスが格納されているということは、そのポインタがそのアドレスのデータ(変数など)を指しているということになる。
ポインタ変数の前に * を付けることで、このポインタに格納されたアドレスのデータにアクセス出来る。
* は間接演算子と呼ばれます
code:c
型 変数; //アドレスを参照する変数
//ポインタの宣言
型 *ポインタ変数;
//ポインタの使用
ポインタ変数 = &変数; //変数のアドレスをポインタ変数に格納
//ポインタに数値を入力
*ポインタ変数 = 数値;
例:
code:c
char x; //通常の変数
char y; //通常の変数
char *ptr; //ポインタ変数
x = 'A' //x:Aの値を入れる
y = 'B' //y:Bの値を入れる
ptr = &x; //ptr:xのアドレスの値を入れる
printf("%p\n", ptr); //xのアドレスを表示
printf("%d\n", *ptr); //指定されているアドレスに格納されている値を表示
https://gyazo.com/b8d0b3c77a08045fd7f04d97d61c2adc
ポインタで指定することにより、指定先の数値を変更することが出来る。
例:
code:c
int main(){
//変数の宣言
char x; //xの変数宣言
char *ptr; //ptrのポインタの宣言
//メイン処理開始
x = 'A'; //xに'A'を入れる。
printf("x(1)の値 : %c\n",x); //xの値を表示
ptr = &x; //ptrを、xに指定
*ptr = 'K'; //ptrの値に、'K'を入れる。
printf("x(2)の値 : %c\n",x); //xの値を表示
}
実行結果:https://paiza.io/projects/UTB4bfa1P8XQJ4fCJxudtw
x(1)の値 : A
x(2)の値 : K
ポインタは、配列でも使用可能
例:
code:c
int main(){
//変数の宣言
char arr5 = {'A', 'B', 'C', 'D', 'E'}; //arrの配列宣言
char *ptr; //ポインタの宣言
int i; //カウント用変数
//メイン処理
ptr = arr; //ptrをarrに指定
ptr0 = 'H'; //ptr0にHを入れる。
ptr3 = 'K'; //ptr3にKを入れる。
//arr0~arr4を表示する
for(i=0;i<5;i++) //0~4まで繰り返し
{
printf("arr%dの値 : %c\n",i,arri); //arrの配列表示
}
}
実行結果:https://paiza.io/projects/UTB4bfa1P8XQJ4fCJxudtw
ポインタを指定しない場合はNULLを使用する。
NULLを使用しないで、ポインタを指定しない状態でポインタの指す先にアクセスしようとすると、
メモリアクセスエラーが発生し、プログラムが落ちて即終了する可能性がある。
悪い例:
code:c
int main(){
char *ptr; //ポインタの宣言
printf("*ptr = %d\n", *ptr); //ポインタに格納されている数値の表示
}
良い例:
code:c
NULL:https://daeudaeu.com/null/
https://monozukuri-c.com/langc-nullpointer/
参考:https://daeudaeu.com/pointer/
https://nonbiri-daisuki.com/programing/c-program-use-arrayorpointer/
ポインタを関数に渡す。
code:c
#include <stdio.h>
void funcA(int b)
{
b = 10;
}
void funcB(int *b)
{
(*b) = 200;
}
int main()
{
int a = 1;
printf("a=%d\n", a);
funcA(a);
printf("funcA()の結果 : a=%d\n", a);
funcB(&a);
printf("funcB()の結果 : a=%d\n", a);
return 0;
}
結果:https://paiza.io/projects/0llplWenErAnXSQYZLG6pA?language=c
code:c
typedef struct { //サイズ:int(4)×4=16
int mode1;
int mode2;
int mode3;
int mode4;
}MODE;
typedef struct {
int N1;
char N2;
}N;
typedef struct{ //サイズ:int(4) + MODE(16) =20
int NUM1;
MODE NUM2;
}NUM;
typedef enum{ //サイズ:4
t1,
t2,
t3
}Test;
typedef struct{ //サイズ:Test(4) + int(4) = 8
Test conf1;
}Cnf;
typedef struct{
Test *point;
//Test *point2;
}POINTA;
int main(void){
MODE mode;
NUM num;
printf("MODE:%d\n",sizeof(MODE));
printf("N:%d\n",sizeof(N));
printf("NUM:%d\n",sizeof(NUM));
printf("Test:%d\n",sizeof(Test));
printf("Cnf:%d\n",sizeof(Cnf));
printf("POINTA:%d\n",sizeof(POINTA));
printf("mode.mode1=%d\n",sizeof(mode.mode1));
printf("num.NUM2=%d\n",sizeof(num.NUM2));
return 0;
}
実行結果:https://paiza.io/projects/-IktY0YlY0BtEKVUiSPFlA?language=c
参考:http://www5d.biglobe.ne.jp/~noocyte/Programming/Alignment.html
グローバル変数への保存
code:c
#include <stdio.h>
typedef struct{
int storenum;
int beside;
}Square;
Square squ;
void setNum(int num);
int getNum();
int main(void){
int a =10; //キーコード入力
int b = 0;
setNum(a);
a=0;
//squ.storenum = 0;
a=getNum();
printf("縦の長さ:%d、横の長さ:%d",a,b);
return 0;
}
void setNum(int num){
squ.storenum = num;
}
int getNum(){
return squ.storenum;
}
実行結果:https://paiza.io/projects/g45csCVPVpZrrezPMnATGA?language=c
平均
https://paiza.io/projects/RDNyOp5XNBpN6wBoMEIOzA
ポインタとループ処理
code:c
#include <stdio.h>
void func1();
void func2();
int main(void){
int set=0;
int i = 0;
// Your code here!
while(1){
func1();
func2(&set);
i += 1;
printf("i=%d\n",i);
if(i==3)break;
}
}
void func1(){
int a=0;
a += 1;
printf("a=%d\n",a);
}
void func2(int *b){
(*b) += 10;
printf("b=%d\n",*b);
}
結果:https://paiza.io/projects/tAxKXbMtPaGhQw12EFrRUg?language=c
配列とポインタ
code:c
#include <stdio.h>
#define SAMP_BUF_LEN 4096
unsigned short g_SampBufRevSAMP_BUF_LEN __attribute__ ((aligned (4)));
int main(void){
// Your code here!
unsigned short *p;
p = &g_SampBufRev0;
for(int i=0;i<20;i++){
pi = i;
printf("%d\n",pi);
}
}
https://paiza.io/projects/p-RxTcmcRe4nuxFBUq-z3g
https://paiza.io/projects/RwAkL4Bd3oHXKf70U4luCA?language=c
#プログラミング学習