【初心者歓迎】C/C++室 Ver.30【環境依存OK】

このエントリーをはてなブックマークに追加
952デフォルトの名無しさん:2006/10/14(土) 02:47:04
普通、stdoutとかの再割り当てにはfreopen()を使うような気がする
953943: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
もうわけがわかりません…
954943:2006/10/14(土) 04:16:10
>>949
(*pt)*(*(pt++))の場合
もし乗算演算子*の右側から評価されれば
(*(pt+1))*(*(pt+1))になって
乗算演算子*の左側から評価されれば
(*pt)*(*(pt+1))になるってことでしょうか?
そもそも後置インクリメントは式の値を返した後に代入するものだとおもってました。
955デフォルトの名無しさん:2006/10/14(土) 09:33:36
>>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より先かもしれないし、後かもしれない。


956デフォルトの名無しさん:2006/10/14(土) 13:37:45
>953
まずは↓読め
http://www.kouno.jp/home/c_faq/c3.html#0

>955
未定義だと鼻から悪魔を思い浮かべるので、評価順序の場合は未規定か不定と書くのが望ましいと思う。
957デフォルトの名無しさん:2006/10/14(土) 13:52:29
>>956
「不定」は違うだろ。
958デフォルトの名無しさん:2006/10/14(土) 14:55:56
未規定 コンパイラの好きにしろ 
未定義 HDD消されても知らんぞ

とかの方がわかりやすいよね

959デフォルトの名無しさん:2006/10/14(土) 16:05:50
未定義 ツンデレAI美少女がPCから出てきても知らんぞ
960943:2006/10/14(土) 16:57:33
>>955>>956
レスありがとうございます。
お恥ずかしいことに色々と勘違いしていたようです。
>>955
なるほど、右結合や左結合の捉え方を誤っていたようですね。
よくわかりました。

皆様ご丁寧にありがとうございました。
961デフォルトの名無しさん:2006/10/14(土) 17:45:39
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回で済ます方法は無いでしょうか?
962デフォルトの名無しさん:2006/10/14(土) 17:50:21
>>961
template
963デフォルトの名無しさん:2006/10/14(土) 18:01:57
>>961
設計を見直す。
964デフォルトの名無しさん:2006/10/14(土) 18:11:42
質問です
自分のサイズよりも大きな構造体のポインタに対するキャストが
うまく動くかどうかは実装依存でしょうか?

例えばこんなコードです
#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;
}

965デフォルトの名無しさん:2006/10/14(土) 18:16:29
それでうまくいかない処理系を知らない
966961:2006/10/14(土) 18:38:30
>>962
具体的にどう書けばいいんでしょうか?
プログラミング言語c++を読んでみたのですが、自分には書き方が判りませんでした。

>>963
やっぱり設計を変えたほうがいいですか。

int,doubleを受け取るんじゃなくて、fooのようなクラスfooArgを受け取るようにして、
hoge::set(1) が hoge::set( fooArg(1)) に自動変換するようにすればいいとか?
967962: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); }
};
968961:2006/10/14(土) 19:18:59
>>967
ありがとうございます。動きました。

class hogeの前にtemplate書いてみたり、メソッドの宣言は普通に型を指定して、
実体の方だけだけtemplateをつけて動かなかったのです…
969964:2006/10/14(土) 20:46:02
>>965
ありがとうございます
こういったコードが必要になったので悩んでいたのですが
気にせず使うことにしました
970デフォルトの名無しさん:2006/10/14(土) 21:00:25
>>969
その例だとキャストする意味が分からん。
キャストしないで済ませられないか、よく考えてから使えよ。
971デフォルトの名無しさん:2006/10/14(土) 21:08:57
>>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ではこれが出来なかったらメッセージのやり取りが出来ないけどな。
972デフォルトの名無しさん:2006/10/14(土) 21:15:50
>>971
それは実装依存かな。少なくとも正しく動作する保証は無いだろう。
973971:2006/10/14(土) 21:20:57
>>972
PSなんかではアライントメントの関係でおかしくなる場合があるってfj.comp.lang.cで話題になったことがあったと思う。
974デフォルトの名無しさん:2006/10/14(土) 21:24:28
>>973
アライメントが不正な場合に未定義動作となることは規格に明記されている。
975971:2006/10/14(土) 21:26:56
>>974
だとすると>>971はやっぱ未定義だな。
本当に>>964がこういうのを意図してたかどうかはわからんが。
976デフォルトの名無しさん:2006/10/14(土) 21:32:58
VC++.net、C言語にてUDPのプログラムを作っています。
現在、サーバ側がどうにかしてIPを調べクライアント側に伝え、
クライアントがサーバのIP・ポートを手入力して繋いています。
それをサーバ側がロビーサーバに登録し、クライアントがロビーサーバにアクセスしてクリックだけで接続できるようにしたいと考えています。
その際、サーバ側のグローバルIPをプログラムで取得してロビーサーバに保存させたいのですが、
どうすればグローバルIPを取得することが出来るのでしょうか。
977デフォルトの名無しさん:2006/10/14(土) 21:47:30
971はわからないが、964は平気であるはず。
構造体へのポインタは先頭要素の型へのポインタにキャストして平気であるという規定があったはず。
978デフォルトの名無しさん:2006/10/14(土) 21:49:56
>>977
964 はその規定にかかわらず、元の型に戻してから使ってるので問題ない。
979964: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なのは、ポインタのサイズと関係があるんですかね
980964:2006/10/14(土) 21:59:17
>>977
>構造体へのポインタは先頭要素の型へのポインタにキャストして平気であるという規定があったはず。
なるほど、参考になります

(LPCREATESTRUCT)lParamといったコードがあるので
LPCREATESTRUCTについて調べてみたところ
tagCREATESTRUCTの最初の引数はLPVOID (void *)でした
ということは、データを受け渡しを考えた時は
構造体の最初のメンバに気を配らないとダメなのでしょうか?
981964:2006/10/14(土) 22:03:40
>>978
ということは大丈夫っぽいですね
色々ありがとうございました
982デフォルトの名無しさん:2006/10/14(土) 23:00:01
>>976
ロビーサーバに訊いたら駄目なのか
983デフォルトの名無しさん:2006/10/14(土) 23:21:12
>>979
LPARAMは単なる整数型だ。
ポインタ型をポインタ型以上の大きさを持つ整数型に変換して、また元のポインタ型に戻して使うのは問題ない。

現在LPARAMは、ポインタ型と同じ大きさを持つ符号有り整数型と定義されている。
984976:2006/10/14(土) 23:25:25
>>982
 サーバA   サーバB   サーバになる人がロビーサーバで登録
  登録↓   ↓登録    
    [ロビーサーバ]    ロビーサーバがサーバのIP・ポートを保持し、クライアントに表示させる(名前+ボタンとか)
  参照↑ ↑↑ ↑参照
   クラA || クラD  クライアントはロビーサーバにアクセスし、 
     クラB クラC     行きたいサーバのボタンを押して接続

ロビーサーバに聞くとしても、サーバ側のIPを受け取らないといけませんよね。
サーバ側のグローバルIPの取得方法がわからず、IPを渡すという作業が出来ずに詰まっていて躓いている状態です。
985デフォルトの名無しさん:2006/10/15(日) 00:33:37
ロビーサーバがサーバA・Bから接続を受けた時点でグローバルIPは分かるだろ。
986デフォルトの名無しさん:2006/10/15(日) 00:39:32
あ、サーバ登録時もUDP使ってるのか?
987デフォルトの名無しさん:2006/10/15(日) 00:45:41
CもC++も全く関係ないな
988デフォルトの名無しさん:2006/10/15(日) 00:53:16
ネットワークプログラミング相談室 Port18
http://pc8.2ch.net/test/read.cgi/tech/1159692799/l50
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;}
バクがわかりません。教えていただけないでしょうか?
990デフォルトの名無しさん:2006/10/15(日) 01:48:46
ここまで堂々としたマルチもめずらしいな
991デフォルトの名無しさん:2006/10/15(日) 01:51:31
max、minマクロは既に定義されてるのでエラーになる。
max、min関数を宣言する前に

#undef max
#undef min

と追加するか、max関数とmin関数自体を削ると通るはず。(bcc5.5なら)


しかしそのコーディングスタイルはなんかの苦行か?
992デフォルトの名無しさん:2006/10/15(日) 01:57:37
gcc(オプション-Wall)で試したけどエラーでないよ。
993デフォルトの名無しさん:2006/10/15(日) 02:02:58
>>991の言うとおりbccで試したらエラー出たよ
#undef追加したらエラー出なくなったよ
994デフォルトの名無しさん:2006/10/15(日) 02:12:31
>>991 有難うございました。
   追加した所、通りました。
   関数名を変えても通りました(^^)v
   このコーディングは、掲示板が生み出したて感じですねw。

>> 驚きです(゜o゜)。
995デフォルトの名無しさん:2006/10/15(日) 02:19:08
激しい電波をキャッチしました。
996デフォルトの名無しさん:2006/10/15(日) 02:34:26
bccってそんなに腐っていたのか。
Windows.hをincludeすると、min, maxというマクロがあるのは知っていたが。
でも何故なんだろう。
STLならnamespaceに入っているはずだし。
997デフォルトの名無しさん:2006/10/15(日) 04:29:00
質問です。

initされ、unlock状態のmutexをlockしようとするとプロセスが落ちるのですが、
理由は何が考えられるでしょうか。

siginfo.txtによると、SIGSEGV(BADADRS:0x00000000)です・・・
998デフォルトの名無しさん:2006/10/15(日) 05:09:23
コードが間違ってる
999デフォルトの名無しさん:2006/10/15(日) 06:30:54
h
1000小倉優子 ◆en0rG2J.f6 :2006/10/15(日) 06:31:25
1000ならジュースでも飲むか
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。