構造体のポインタの動作及びそれ故書けない関数
こんにちは.c言語でのstructureのポインタについての質問,及びその動作ゆえに自分のやりたい書き方ができないので,アドバイスをお願いしたいと思います.
まずは,structureのポインタを使った計算が謎の動きをするので,説明して頂けたらと思います.ubuntu 12.04 64bit, コンパイラはgcc 4.6.3, ただg++でやっても同じ動きでした.
#include <stdio.h>
int main(int argc, char **argv)
{
struct state_ {
double pos[3];
double att[3];
}state = {
{ 1.0, 2.0, 3.0 },
{ 4.0, 5.0, 6.0 },
};
double *state_ptr;
state_ptr = &state.pos[0];
printf("%f\t%f\t%f\t%f\t%f\t%f\n", *state_ptr, *(++state_ptr),*(++state_ptr), *(++state_ptr), *(++state_ptr), *(++state_ptr));
double *pos_ptr, *att_ptr;
pos_ptr = &state.pos[0];
att_str = &state.att[0];
printf(“head of pos %f, head att %f\n”, *pos_ptr, *att_ptr);
return 0;
}
こうすると,結果は
6.000000 6.000000 6.000000 6.000000 6.000000 6.000000
head of pos 1.000000, head of att 4.000000
はて,どうなっているのでしょうか?少なくとも1行目の最初の6.0はpos[0]の1.0のはずなのでは?
ちなみに-Wallをつけると,
struct_double_pointer_test.c:17:54: warning: operation on ‘state_ptr’ may be undefined [-Wsequence-point]
が出ます.
また,++state_ptrをstate_ptr++に変えると結果は
6.000000 6.000000 5.000000 4.000000 3.000000 2.000000
そして -O2をつけると
6.000000 5.000000 4.000000 3.000000 2.000000 1.000000
基本的にメンバーの順番がひっくり返ってますね.これは一体どういうことなんでしょう?undefinedと言われてるから何が起こっても変じゃないでしょ,と言われればそうなんですが,何かなっとくのいく説明があれば嬉しいです.pos_ptr, att_ptrで単体で出すと正しく出るので,*(pointer++)の動作がundefinedってことなんですよね?僕は
1.0 2.0 3.0 4.0 5.0 6.0
となってくれると思った訳です.(ちなみにMacOS gccではこうなりました)structureの中で順番に上からアドレスが振られると思ったので.そして2番目の質問に移る訳ですが,上記の僕の予想通り動いた場合,2つ構造体のポインタを渡して,順番に中身を積分させていくような計算が以下のようにできると思いました.
void integrate(struct state_ *x, struct state_ *dx, num_of_double)
{
const float timestep = 0.01
int i;
for(i=0; i<num_of_double, i++){
*x += *dx*timestep;
x++, dx++;
}
}
両方きれいに順番がひっくり返るなら上の書き方でも積分させた値は同じになるからいい?とは言えど怖くてもちろん使えません.こういう計算をさせる場合は,構造体のポイタを渡さずに配列ごとに計算させるんですかね?&pos[0]と&pos_dx[0]を渡すなど?一般的にどういう書き方をするものなのかが知りたいです.
お礼
ご回答ありがとうございます。 三次元配列の例は具体的でわかりやすかったです。 やっぱりメモリ上でどう確保されて、どうアクセスするかがイメージ出来ていないといけないんだなと思いました。 またうちの会社では int *p = (int *)malloc(sizeof(int) * n); 一本ですね。もうひとつの書き方は初めて見ました。この書き方だとint*型にキャストする必要がないんですね。 まだまだ勉強しないといけないことがたくさんあると感じるご回答でした。 これからも勉強していこうと思います。 また、お礼が遅れまして失礼しました。