ポインタと配列

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
dyad

ポインタと配列

#1

投稿記事 by dyad » 2年前

先々週にお世話になりましたdyadです。
新ゲームプログラミングの館を一通り見終え、とりあえずサンプルを改変してみようとキーボードの入力状態の取得(2.9章)をファイル分割しようとしたのですがうまくいかなかったので質問させてください。
ここ数日ポインタに関するページ等を検索して勉強していたのですが、正直理解できたとは言い難く基本的な部分で間違っているような気がしています…
main.cpp

コード:

#include "DxLib.h"
#include"Key.h"

int Key[256]; // キーが押されているフレーム数を格納する

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); 
	int x = 0;
        while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		gpUpdateKey(&Key[256]);
		DrawFormatString(x, 0, GetColor(255, 255, 255), "?!"); // x,0 の位置に白で ?! を描画

		if (Key[KEY_INPUT_RIGHT] == 1) { // 右キーが押された瞬間なら
			x = x + 50;                 // xを50加算
		}
	}
	DxLib_End(); // DXライブラリ終了処理
	return 0;
}
Key.cpp

コード:

#include"DxLib.h"
#include"Key.h"

static void gpUpdateKey(int *Key) {
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll(tmpKey); // 全てのキーの入力状態を得る
	for (int i = 0; i<256; i++) {
		if (tmpKey[i] != 0) { // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		}
		else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
}
Key.h

コード:

#pragma once
void gpUpdateKey(int *Key);
結果としてLNK2019:未解決の外部シンボルとLNK1120:1件の未解決の外部参照のエラーが返ってきました。
また、ポインタを勉強するにあたっておすすめのサイト等教えていただければ幸いです…

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: ポインタと配列

#2

投稿記事 by purin52002 » 2年前

こんにちは。

パッとコードを見て一番最初にうん?となったのがKey.cppのstatic関数です。

static変数は知ってるけどstatic関数は初めて見たぞ?
ということで調べたところ、static関数はそのソースファイル(今回はKey.cpp)の中でのみ使える関数という意味らしいです。

つまり、
Key.cppでUpdateKeyを定義(staticで)したけどmainから呼び出せるUpdateKeyは定義されてないよ!
というエラーではないでしょうか。
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: ポインタと配列

#3

投稿記事 by purin52002 » 2年前

あと、main文で呼んでいるUpdateKeyですが引数がすごいことになっています^^;

ポインタはとっつきにくいですが、イメージさえできれば何とかなります。

ポインタとはデータが格納されている場所(メモリのアドレス)を示します。
配列とはデータを連続して格納したものです。

たとえば
int x=1;
int y=2;
と宣言するとデータは

1,空白,空白,2

のようにバラバラに格納されます。

しかし、
int z[2]={1,2};
と宣言するとデータは

1,2,空白,空白

のように連続して格納されます。
だからz[0]というのはzの1番目のデータを指し示します。(cだと0から数字を数え始めます。)
ということはz[2]にはデータが格納されていませんね?
配列のインデックスは最大でも「配列の大きさ-1」になるというわけです。

そして、ポインタとは切っても切れない&演算子。
これはデータを格納する場所を示します。

&z「1」はz[1](=2)の場所を示すわけですね。

コード:

void func(int *pz)
{
    for(int i=0;i<2;++i)printf("%d\n",pz[i]);
}
では&z[1]をfuncの引数に渡すとどういう結果になるでしょう?

pz[0]=2,pz[1]=空白

となってしまいます。

じゃあ何を引数に渡せばいいのでしょうか?

疲れたのでここで説明終わりです^^;
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

dyad

Re: ポインタと配列

#4

投稿記事 by dyad » 2年前

あ、しまった…本当だ…
カプセル化しようとするあまり先走ってしまったみたいです。ここはstaticいりませんでしたね…
static外せばきちんとビルドしました。

ただエラー吐かなかったのは良かったのですが右キーを押しても反応がなく、やはりどこかでミスをしてるみたいです。
わからない…

dyad

Re: ポインタと配列

#5

投稿記事 by dyad » 2年前

あ、すいません、ポインタについて書いてくださってましたね。
よく見直してみます。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: ポインタと配列

#6

投稿記事 by purin52002 » 2年前

ネタバレすると、main文で呼んでるgpUpdateKey(&Key[256]);が悪いんじゃないかなぁ、と思います。
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

dyad

Re: ポインタと配列

#7

投稿記事 by dyad » 2年前

ありがとうございました。配列のポインタについて調べて修正したところ、きちんと動作しました…
変数のポインタについてしか調べてなかったのが問題でした…
というか&と*についてまだ少しごっちゃになってるんですが、プログラムしながら覚えていきたいと思います。

一応修正版も書いておきますのでもしマズかったら指摘していただけると幸いです。

コード:

#include "DxLib.h"
#include"Key.h"
 
int Key[256];
 
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK); 
    int x = 0;
        while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {

        gpUpdateKey(Key);      //&Key[256]→Key

        DrawFormatString(x, 0, GetColor(255, 255, 255), "?!");
        if (Key[KEY_INPUT_RIGHT] == 1) {
            x = x + 50;
        }
    }
    DxLib_End();
    return 0;
}
あとKey.cppも直したので一応…
4行目
static void gpUpdateKey(int *Key) {

void gpUpdateKey(int *Key) {

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: ポインタと配列

#8

投稿記事 by purin52002 » 2年前

バッチグーだと思います^^
すごいどうでもいい私ルールですが、配列を引数に渡すときは関数の引数も配列にしておくと見やすいかも?

void gpUpdateKey(int *Key) -> void gpUpdateKey(int Key[])

お疲れさまでした^^
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

閉鎖

“C言語何でも質問掲示板” へ戻る