Ouxiy さんが書きました: ↑4年前
あの、int dx, dy = (2, 2);という書き方ではなぜdx = 2, dy = 2のように1個ずつ初期化されずに実質2になってしまうのですか?また実質2とは何の2でしょうか?座標ではないと思いますが、、、。
C++の規格書(のドラフト)である
N3337から引用します。
まず、8 Declaratorsの1より、変数宣言のうち型(と修飾子)を除いたdx, dy = (2, 2)にあたる部分の文法は
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator initializeropt
となっています。ここで、declaratorはdxやdyのような識別子などのことです。
そして、initializerの定義は、8.5 Initializersの1より
initializer:
brace-or-equal-initializer
( expression-list )
brace-or-equal-initializer:
= initializer-clause
braced-init-list
initializer-clause:
assignment-expression
braced-init-list
initializer-list:
initializer-clause ... opt
initializer-list , initializer-clause ... opt
braced-init-list:
{ initializer-list , opt }
{ }
となっています。
dx, dy = (2, 2)のように書くことで複数の変数を初期化する、というような文法はありません。
「dx」および「dy = (2, 2)」がそれぞれinit-declaratorとして解釈されます。
dx, dy = (2, 2)の= (2, 2)の部分は、=で始まるため、= initializer-clauseに該当します。
そのため、(2, 2)がinitializer-clauseに該当します。
initializer-clauseはassignment-expressionまたはbraced-init-listですが、
(2, 2)は{}で囲まれていないので、braced-init-listではありません。
したがって、(2, 2)はassignment-expressionとなります。
5.17 Assignment and compound assignment operatorsによると、assignment-expressionは
assignment-expression:
conditional-expression
logical-or-expression assignment-operator initializer-clause
throw-expression
となっていますが、今回は代入演算子でもthrowでもないのでconditional-expressionです。
同様に他の演算子でもないのでどんどん辿っていくと、primary-expressionとなり、
5.1 Primary expressionsにあるprimary-expressionの定義の中に
( expression )
があります。(2, 2)はこれに当てはまるので、カッコの中の2, 2がexpressionとして解釈されます。
5.18 Comma operatorより、expressionの定義は
expression:
assignment-expression
expression , assignment-expression
となっており、2, 2はexpression , assignment-expressionに当てはまります。
(2はprimary-expressionの定義の1つであるliteralとなります)
そして、このコンマ演算子の効果は、同じく5.18より
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-
value expression (Clause 5). 83 Every value computation and side effect associated with the left expression
is sequenced before every value computation and side effect associated with the right expression. The type
and value of the result are the type and value of the right operand; the result is of the same value category
as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field.
となっています。
すなわち、「まず、コンマの左辺が評価される。
コンマの左辺の評価が完了したあと、コンマの右辺が評価される。
コンマ演算子の評価結果は、右辺の評価結果になる。」ということです。
今回の2, 2の右辺は2なので、評価結果は2になります。
「実質2」とは、このコンマ演算子の右辺の2です。
また、dx, dy = (2, 2)においては、dxの方にはinitializerがついていないため、初期化されません。
8.5より、正確にはdefault-initializeされますが、
int型の自動変数のdefault-initializeは「初期化しない(no initialization is performed)」(8.5の6)なので、
値は不定になります。(8.5の11)
Ouxiy さんが書きました: ↑4年前
gh[12]はint型であるため
式中のgh[12]はint型(ただし
範囲外へのアクセスとなり、危険!)ですが、
変数宣言中のgh[12]をint型というのはおかしいでしょう。
このgh[12]は、N3337の8 Declaratorsにあるnoptr-declaratorの定義のうち、
noptr-declarator [ constant-expression
opt ] attribute-specifier-seq
optに該当します。
これは宣言の一部であり、これの型を考えるのはおかしいと考えられます。
Ouxiy さんが書きました: ↑4年前
int型の変数playerphotoに変えて、関数LoadDivGraphに代入してみたのですが
関数の引数としているだけで、関数に代入はしていないですね。
Ouxiy さんが書きました: ↑4年前
赤い下線部となり、エラーとなります。確か同じ型の置き換えは出来たと思うのですが、関数LoadDivGraphもint型を引数にとっているため大丈夫かと思ったらダメでした。なぜでしょうか。
DXライブラリの関数LoadDivGraphはint型の引数も取りますが、
リファレンスを見ると、
int LoadDivGraph( char *FileName , int AllNum ,
int XNum , int YNum ,
int XSize , int YSize , int *HandleBuf ) ;
となっており、playerphotoを渡している第7引数はint型ではなくint*型です。
そのため、第7引数にint型の値を渡してはいけません。
コード:
int playerphoto;
LoadDivGraph("charall.png", 1, 1, 1, 49, 66, &playerphoto);//画像読み込み
のように、ポインタ演算子&によってint型の変数のポインタを取り、
画像のハンドルをそこに
1個だけ入れることはできるでしょう。
ただし、
コード:
int playerphoto;
LoadDivGraph("charall.png", 12, 3, 4, 49, 66, &playerphoto);//危険!
のように複数のハンドルを入れようとしてしまうと、
int型の変数にはint型1個分の領域しか無いのに、
複数のデータを入れようとしてしまい、はみ出してしまって
危険です。
Ouxiy さんが書きました: ↑4年前
DrawGraph(dx, dy, gh[5], FALSE)の入れている部分は間違っていないと思うのですが、
私は間違っていると思います。
ループ前に入れるということは、ループ前の1回しか実行されないということであり、
そこにキー入力が反映されることは無いでしょう。
ついでにDrawGraph(nx, ny, playerphoto, FALSE);も怪しいです。
キャラクターが1ドットずつしか動かない仕様でいいのでしょうか?
Ouxiy さんが書きました: ↑4年前
キャラの最初の位置座標
コード:
int dx=2, dy =2 ; // 最初のキャラのX座をdxとY座標をdyである。配列の真ん中の0を最初の座標としたため(2,2)となる
も
コード:
int idou[5][5] = {
{1,1,1,1,1 },
{1,0,0,0,1 },
{1,0,0,0,1 },
{1,0,0,0,1 },
{1,1,1,1,1 },
};
に反映されているか心配です。というのも移動後の座標の数字1か0で移動可能かの変数
コード:
int nx = 0;//移動後のキャラのx座標の0か1の数字
int ny = 0;//移動後のキャラのy座標の数字
を作りましたが、形的に
コード:
int nx = 0;
int ny = 0;
と
が似ていたり、int idou[5][5]の座標との関係がしっかりかけていないような気がしてきたためです。ただ、idou[5][5]での真ん中の0の座標を表すのはint dx=2, dy =2 ;で良いと思うので、何とも言えないのですが。
あと何をどのように修正すればいいでしょうか。
「反映されている」の意味がよくわからないです。
「0か1」というのはよくわからないですが、同じ「座標」を扱う変数が似た形になるのは自然でしょう。
(ただし、使うときに取り違えないように注意が必要かもしれません)
idou[5][5]での真ん中の座標を表すのはint dx=2, dy =2 ;でいいでしょう。
Ouxiyさんのコードを、希望の動作をするように修正すればいいでしょう。