【初心者歓迎】C/C++室 Ver.30【環境依存OK】 普通、stdoutとかの再割り当てにはfreopen()を使うような気がする
953 :
943 :2006/10/14(土) 04:14:57
>>948 ,949
レスありがとうございます。
>>948 一応カッコをつけなかったのはつけなかったときにどういう動作をするか見てみたかったからです。
優先順位と結合法則については手持ちの参考書に書いてあるのですが、
間接参照の*も++も--もすべて同じ優先順位で右→左の結合(右結合)とかかれていました。
(++と--は前置とか後置とか区別されてませんでした)
たとえばコード1の5行目のfor文*++pt=*pt**ptで考えてみると、
間接参照の*と前置インクリメントが優先順位が高くなりますよね。
で、二つとも右結合だから一番右端の*ptそして乗算*をはさんで左にある*pt、
最後に*++ptの順番に演算していくことになります。つまり
(*(pt+1))=(*pt)*(*pt)
配列のアドレスに直すと、
(*&ia[1])=(*&ia[0])*(*&ia[0])
になり、結果が合いません…。
おっしゃるように「前置インクリメントと間接参照の*は同じ優先順位で左結合
後置インクリメントが前者二つより優先順位が高く右結合」が正しく参考書が
間違えているぽいですね。ただ、同じようにコード1でやってみると、
*++pt=*pt**ptなので
参考書の考え方と同じく優先順位は間接参照の*と前置インクリメントが高くなります。
ただし結合法則が左結合になるため、まず++pt→*(++pt)→代入演算子の右にある*pt
→右端の*ptの順で演算していくとこになります。つまり
(*(pt+1))=(*(pt+1))*(*(pt+1))になって、配列の形にすると
(*&ia[1])=(*&ia[1])*(*&ia[1])になり、結果が合います。
ただこの場合は、式にカッコをつけて*++pt=(*pt)*(*pt)とした場合でも、
実行結果がカッコをつけなかった場合と同じになってしまいます…orz
もうわけがわかりません…
954 :
943 :2006/10/14(土) 04:16:10
>>949 (*pt)*(*(pt++))の場合
もし乗算演算子*の右側から評価されれば
(*(pt+1))*(*(pt+1))になって
乗算演算子*の左側から評価されれば
(*pt)*(*(pt+1))になるってことでしょうか?
そもそも後置インクリメントは式の値を返した後に代入するものだとおもってました。
>>953 演算子の優先順位と結合法則から、(*(++pt))=(*pt)*(*pt) となることについての理解は正しい。
>二つとも右結合だから一番右端の*ptそして乗算*をはさんで左にある*pt、
>最後に*++ptの順番に演算していくことになります。
これは正しくない。
右結合というのはたとえば a=b=c=d が a=(b=(c=d)) と右側から順に結合するということ。
2項(or3項)演算子の非演算子が、どれから順に評価されるかは(一部の例外を除き)未定義。
つまり、A=B*C という式のA, B, C それぞれの部分がどの順序で評価されるかは決まっていない。
++pt と *pt のどっちが先に評価されるかで、結果は変わる。
上で書いた一部の例外というのは &&, ||, ,(カンマ演算子)の3つ。
これらは非演算子が左、右の順で評価されることが決まっている。
>>954 これも、
>そもそも後置インクリメントは式の値を返した後に代入するものだとおもってました。
pt++ を評価するとその値は pt であり、pt自身はインクリメント(+1)される。
ただし、ptがインクリメントされるタイミングは、pt++の評価後であって、
式全体(*pt)*(*(pt++))の評価後ではない。
pt++が評価されるのが*ptより先かもしれないし、後かもしれない。
未規定 コンパイラの好きにしろ 未定義 HDD消されても知らんぞ とかの方がわかりやすいよね
未定義 ツンデレAI美少女がPCから出てきても知らんぞ
960 :
943 :2006/10/14(土) 16:57:33
>>955 >>956 レスありがとうございます。
お恥ずかしいことに色々と勘違いしていたようです。
>>955 なるほど、右結合や左結合の捉え方を誤っていたようですね。
よくわかりました。
皆様ご丁寧にありがとうございました。
class foo; class hoge { private: foo* mpFoo; public: (略) void set( int val) { if (mpFoo) mpFoo->set(val); } void set( double val) { if (mpFoo) mpFoo->set(val);} }; class fooはintとdoubleのどちらの型のデータを持っているか判る 数値情報を持つクラスです。 hoge::set()の場合は1行で書けますが、 他にもまったく同じ処理なのに、 引数の型が違うだけのメソッドがいます。 これをint,doubleで2回づつ書くのではなく、 1回で済ます方法は無いでしょうか?
質問です 自分のサイズよりも大きな構造体のポインタに対するキャストが うまく動くかどうかは実装依存でしょうか? 例えばこんなコードです #include<stdio.h> struct mydata{int a,b,c,d;}; int main(){ int *p; mydata da={1,2,3,4}; p = (int *)&da; printf("%d %d %d %d\n",((mydata*)p)->a,((mydata*)p)->b,((mydata*)p)->c,((mydata*)p)->d); return 0; }
それでうまくいかない処理系を知らない
966 :
961 :2006/10/14(土) 18:38:30
>>962 具体的にどう書けばいいんでしょうか?
プログラミング言語c++を読んでみたのですが、自分には書き方が判りませんでした。
>>963 やっぱり設計を変えたほうがいいですか。
int,doubleを受け取るんじゃなくて、fooのようなクラスfooArgを受け取るようにして、
hoge::set(1) が hoge::set( fooArg(1)) に自動変換するようにすればいいとか?
967 :
962 :2006/10/14(土) 18:50:48
>>966 class hoge {
private:
foo* mpFoo;
public:
template<class T>
void set(T val) { if (mpFoo!=NULL) mpFoo->set(val); }
};
968 :
961 :2006/10/14(土) 19:18:59
>>967 ありがとうございます。動きました。
class hogeの前にtemplate書いてみたり、メソッドの宣言は普通に型を指定して、
実体の方だけだけtemplateをつけて動かなかったのです…
969 :
964 :2006/10/14(土) 20:46:02
>>965 ありがとうございます
こういったコードが必要になったので悩んでいたのですが
気にせず使うことにしました
>>969 その例だとキャストする意味が分からん。
キャストしないで済ませられないか、よく考えてから使えよ。
>>970 >>964 は「自分のサイズよりも大きな構造体」
って書いてるから例が今ひとつなだけで、こういうことを言いたいのでは?
#include<stdio.h>
struct mydata{int a,b,c,d;};
struct mydata2{int a,b,c,d,e;}
int main(){
mydata2 *p;
mydata da={1,2,3,4};
p = (mydata2 *)&da;
printf("%d %d %d %d\n",p->a,p->b,p->c,p->d);
return 0;
}
まあWindowsではこれが出来なかったらメッセージのやり取りが出来ないけどな。
>>971 それは実装依存かな。少なくとも正しく動作する保証は無いだろう。
973 :
971 :2006/10/14(土) 21:20:57
>>972 PSなんかではアライントメントの関係でおかしくなる場合があるってfj.comp.lang.cで話題になったことがあったと思う。
>>973 アライメントが不正な場合に未定義動作となることは規格に明記されている。
975 :
971 :2006/10/14(土) 21:26:56
976 :
デフォルトの名無しさん :2006/10/14(土) 21:32:58
VC++.net、C言語にてUDPのプログラムを作っています。 現在、サーバ側がどうにかしてIPを調べクライアント側に伝え、 クライアントがサーバのIP・ポートを手入力して繋いています。 それをサーバ側がロビーサーバに登録し、クライアントがロビーサーバにアクセスしてクリックだけで接続できるようにしたいと考えています。 その際、サーバ側のグローバルIPをプログラムで取得してロビーサーバに保存させたいのですが、 どうすればグローバルIPを取得することが出来るのでしょうか。
971はわからないが、964は平気であるはず。 構造体へのポインタは先頭要素の型へのポインタにキャストして平気であるという規定があったはず。
>>977 964 はその規定にかかわらず、元の型に戻してから使ってるので問題ない。
979 :
964 :2006/10/14(土) 21:54:22
>>970-975 レスありがとうございます
すみません、例が悪かったですね
971さんの仰るとおりウィンドウメッセージ関連です
規格上は未定義なんですねorz
必要になった状況というのは
ユーザ定義メッセージを送るPostMessageの引数です
自作コントロールでWM_APP_HOGEHOGEを定義して
PostMessageの引数のLPARAMに受け渡すデータを
パックして送ろうとしたんですが
私の環境では、LPARAMはlong型なので
mydata(受け渡し用データ)のほうがかなりサイズが大きく、
こういったキャストを利用してよいものかと思い質問しました
WEBでWM_USERやWM_APPの使い方を調べても、
WPARAMやLPARAMにデータを入れて送っている例がなかなか見つからないので
直接キャストしてみたらとりあえずは動いているようです
けど不備があったら嫌だな^^;
もしかしてLPARAMがlongなのは、ポインタのサイズと関係があるんですかね
980 :
964 :2006/10/14(土) 21:59:17
>>977 >構造体へのポインタは先頭要素の型へのポインタにキャストして平気であるという規定があったはず。
なるほど、参考になります
(LPCREATESTRUCT)lParamといったコードがあるので
LPCREATESTRUCTについて調べてみたところ
tagCREATESTRUCTの最初の引数はLPVOID (void *)でした
ということは、データを受け渡しを考えた時は
構造体の最初のメンバに気を配らないとダメなのでしょうか?
981 :
964 :2006/10/14(土) 22:03:40
>>978 ということは大丈夫っぽいですね
色々ありがとうございました
982 :
デフォルトの名無しさん :2006/10/14(土) 23:00:01
>>979 LPARAMは単なる整数型だ。
ポインタ型をポインタ型以上の大きさを持つ整数型に変換して、また元のポインタ型に戻して使うのは問題ない。
現在LPARAMは、ポインタ型と同じ大きさを持つ符号有り整数型と定義されている。
984 :
976 :2006/10/14(土) 23:25:25
>>982 サーバA サーバB サーバになる人がロビーサーバで登録
登録↓ ↓登録
[ロビーサーバ] ロビーサーバがサーバのIP・ポートを保持し、クライアントに表示させる(名前+ボタンとか)
参照↑ ↑↑ ↑参照
クラA || クラD クライアントはロビーサーバにアクセスし、
クラB クラC 行きたいサーバのボタンを押して接続
ロビーサーバに聞くとしても、サーバ側のIPを受け取らないといけませんよね。
サーバ側のグローバルIPの取得方法がわからず、IPを渡すという作業が出来ずに詰まっていて躓いている状態です。
ロビーサーバがサーバA・Bから接続を受けた時点でグローバルIPは分かるだろ。
あ、サーバ登録時もUDP使ってるのか?
CもC++も全く関係ないな
989 :
デフォルトの名無しさん :2006/10/15(日) 01:40:18
『宣言が正しく終了していない』とエラーがでました。 #include <stdio.h> #include <time.h> #include <stdlib.h> #define SIZE 20 int Scores[SIZE]; /*グローバル変数宣言*/ int max(int a, int b) { if(a<b) return b;else return a; } int min(int a, int b){ if(a<b) return b;else return a; } int main(void){ int i;double ave,sum; srand(894u); for (i=0; i<SIZE; i++) Scores[i] = (int)(rand()/(RAND_MAX+1.0)*301)-100; for (i=0; i<SIZE; i++){ Scores[i]=min(Scores[i],0); Scores[i]=max(Scores[i],100);} for (i=0; i<SIZE; i++){ sum += (double)Scores[i];} ave =sum/SIZE; printf("Answer is %6.2f.\n",ave); return 0;} バクがわかりません。教えていただけないでしょうか?
ここまで堂々としたマルチもめずらしいな
max、minマクロは既に定義されてるのでエラーになる。 max、min関数を宣言する前に #undef max #undef min と追加するか、max関数とmin関数自体を削ると通るはず。(bcc5.5なら) しかしそのコーディングスタイルはなんかの苦行か?
gcc(オプション-Wall)で試したけどエラーでないよ。
>>991 の言うとおりbccで試したらエラー出たよ
#undef追加したらエラー出なくなったよ
994 :
デフォルトの名無しさん :2006/10/15(日) 02:12:31
>>991 有難うございました。
追加した所、通りました。
関数名を変えても通りました(^^)v
このコーディングは、掲示板が生み出したて感じですねw。
>> 驚きです(゜o゜)。
激しい電波をキャッチしました。
bccってそんなに腐っていたのか。 Windows.hをincludeすると、min, maxというマクロがあるのは知っていたが。 でも何故なんだろう。 STLならnamespaceに入っているはずだし。
997 :
デフォルトの名無しさん :2006/10/15(日) 04:29:00
質問です。 initされ、unlock状態のmutexをlockしようとするとプロセスが落ちるのですが、 理由は何が考えられるでしょうか。 siginfo.txtによると、SIGSEGV(BADADRS:0x00000000)です・・・
コードが間違ってる
h
1000 :
小倉優子 ◆en0rG2J.f6 :2006/10/15(日) 06:31:25
1000ならジュースでも飲むか
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。