トップページ⇒tech
1001コメント300KB

C++相談室 part9

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
現在最高のプログラム言語と言われるC++についてのご相談承ります。
(´∀`).。o(関連URLは>>2-5の辺り)
0232デフォルトの名無しさんNGNG
send
0233デフォルトの名無しさんNGNG
えと、sendについて調べてみました。
実際のところはsendだけでいいんでしょうか?
0234デフォルトの名無しさんNGNG
送るだけならsend
当然sendをするに当たって前準備などをしなければならない。
0235デフォルトの名無しさんNGNG
>>231
とりあえずインターネット(つーか、TCP/IP)とのデータのやりとりには
WinSockっつーAPI体系を使うのが普通なのでそれを調べてみては。

っていうか、このスレって処理系依存、環境依存の話もOKなのか?
漏れは最近見始めたからよく知らないんだが。
C++のスレって言うと、言語仕様だとかライブラリだとかの話題
なんじゃないの?とふと思った。
0236デフォルトの名無しさんNGNG
>>235
環境に依存していたとしても、C++的な問題の可能性があるなら
ここで振ってもいいのでは?

おしえて君は勘弁だが、なんでもかんでも環境依存うぜえという
わけではないと思うぞ。
0237デフォルトの名無しさんNGNG
>>235
> C++のスレって言うと、言語仕様だとかライブラリだとかの話題
原則としてはそうだけど、C++ だと Java や Perl と比較すると標準ライブラリが
全然充実してないし、非標準でも TCP/IP の話などは多くの環境で共通する話
題なので、あまり厳密にやらんでも良いかと。

もし他に適切なスレがあるようなら、やんわりと誘導するって事で。
0238デフォルトの名無しさんNGNG
オブジェクトのファイルへの出力のエレガントな方法を教えてください
シリアライズまでは求めません

つか、みんなどうしてんの??
初心者本はfwirte止まりだし、アホかと。
0239デフォルトの名無しさんNGNG
ToStringメソッドとか
0240 ◆JAPH9PWA NGNG
>>238
普通はoperator <<をオーバーロードするんじゃないかな。


#include <iostream>
namespace my{
class Foo{};

// この関数はnamespaceの中にあるにもかかわらず、適切に呼ばれる
template <class charT >
std::basic_ostream<charT>&
operator << (std::basic_ostream<charT>& os, Foo&)
{
return os << "Foo";
}

} // namespace my

int main ()
{
my::Foo a;
std::cout << a << std::endl;
std::wcout << a << std::endl;
}
0241デフォルトの名無しさんNGNG
<<オーバーロードいいんだけど、

save対象の全種のオブジェクトに対して書く必要があるでしょ。それはエレガントじゃないと。
基本形 MyObj について書くのはいいけど MyObj をSTLと組み合わせた場合なんかどうするのかと。

template<classT> saver& oeprator<<(saver&, T &t) と
template<classT> saver& operator<<(saver&, vector<T> &t)
はあいまいさが解決できずに共存できない罠…

0242 ◆JAPH9PWA NGNG
「save対象の全種のオブジェクトに対して書く必要がない」方法なんてあるの…?。
STLとの組み合わせならfor_each()を使うなりすればいいし。

ていうか
template<class T> saver& oeprator<<(saver&, T &t)
template<class T> saver& operator<<(saver&, vector<T> &t)
これがどう曖昧なのか分からないんですが、私の知識不足?
0243 ◆JAPH9PWA NGNG
って、templateか。

そりゃ曖昧ですよ。
でもoperatorの右オペランドを一般化するなんてそんな無茶な、ってな気がしますが。
0244デフォルトの名無しさんNGNG
template<class T> ostream& operator<<(ostream &o, const T& t) {
 T::const_iterator i, e;
 e = t.end();
 for(i=t.begin(); i!=e; ++i) o << *i;
}

template<> ostream& operator<<(ostream &o, const 任意& t){...}
0245デフォルトの名無しさんNGNG
質問です。以下のプログラムでsizeof(&a)がポインタの
サイズでなく、配列全体のサイズを返すのですが何故ですか?
その他は納得しています。
int main()
{
double d;
int a[2][3];

cout << sizeof(d) << endl; //8と表示
cout << sizeof(&d) << endl; //4と表示
cout << sizeof(int) << endl; //4と表示
cout << sizeof(a) << endl; //24と表示
cout << sizeof(a[0]) << endl;//12と表示
cout << sizeof(&a) << endl; //24と表示??なんで?
}
0246デフォルトの名無しさんNGNG
>>245
親切設計
0247デフォルトの名無しさんNGNG
aなんて物は本来存在せず、単なるシンタックスシュガーだから。
&a[0]と汁
0248デフォルトの名無しさんNGNG
>>247
aは存在するでしょ?a[0]とかがシンタックスシュガーでしょ?
0249デフォルトの名無しさんNGNG
シンタクスシュガー って何? 検索しても、 肝心の解説がみつからん
0250デフォルトの名無しさんNGNG
bcc: 8 4 4 24 12 24
vc++: 8 4 4 24 12 24
g++: 8 4 4 24 12 4
0251デフォルトの名無しさんNGNG
>>248 は?
ポインタと配列勉強しようね。
0252デフォルトの名無しさんNGNG
・シンタックスシュガー
    文法を簡便化するために、作られた記法。
0253デフォルトの名無しさんNGNG
でも、なんで 24になるわけ? 普通a[0]と解釈されるわけでしょ?
エラーとかならわかるけど
0254デフォルトの名無しさんNGNG
>>245
それについての合理的な説明は今まで聴いたこと無い。
ただ文法としてそう決められているというだけ。
K&Rにもそんな記述は載っていないから
素直にsizeof(a)を使うほうが無難。
0255デフォルトの名無しさんNGNG
書いてある本発見
様は、2次元配列か、ポインタの1次元配列か区別が出来ないということらしい

int a[2][3];
int *a[2];
int **a;
int (*a)[3];

どれも a[][]でアクセス出きるのが、上の4パターンのどの宣言かわからんらしい
0256デフォルトの名無しさんNGNG
要は、int a[2][3]に関してsizeof(&a)なんてやるな、と。
0257デフォルトの名無しさんNGNG
逆にsizeof(&a)を使う「べき」ってケースはあるの?
025811NGNG
なんだとおおお!!
sizeof(a)==sizeof(&a)だなんて、そんな馬鹿な!!!!
bccで試したらtypeid(a)==typeid(&a)==INT[2][3]だと!そんなアホな!!!
The result of unary & operator is a pointer to its operand.
って書いてあるだろうが。どこにも特例は出てないぞ!!
でてたら誰か教えてくれ!!!

gccが正しいとみた
0259デフォルトの名無しさんNGNG
↑の4パターン(添字を変えたところで)のどれも 24にはならないような…?
0260デフォルトの名無しさんNGNG
>>247
sizeofの被演算子で配列名指定すると配列全体のサイズ
が返ってくるのは常識だが。その他の文脈ではaは&a[0]
の意味になるはず。
0261デフォルトの名無しさんNGNG
ttp://member.nifty.ne.jp/maebashi/programmer/pointer.html より。

<配列→ポインタの読み換え>

式の中では、配列は「先頭要素へのポインタ」に読み換えられる。

int a[10];

の時、式の中では、a と &a[0]は同じ意味となる。

ただし、以下の個所は例外である。

1、sizeof演算子のオペランド

sizeof演算子は、ポインタのサイズではなく、配列自体のサイズを返す。


2、& 演算子のオペランド

& 演算子は、配列全体のアドレスを返す。
配列から読み換えられたポインタは左辺値を持たないため、
& 演算子のオペランドにはならないはずであるが、この例外規則のため、
& でアドレス(配列の先頭要素のアドレスではなく、配列全体のアドレス)が 取得できる。
この規則は初心者を混乱させることがある
(例えば scanf("%s", buf) でなく、scanf("%s", &buf)と書いても 正常に動いてしまう)が、
メリットは今ひとつわからない。


3、初期化時の文字列リテラル

char の「配列」を初期化する場合の文字列リテラルは、
中括弧内に文字を区切って書く初期化子の省略形である。
char の「ポインタ」を初期化する場合の文字列リテラルとの 違いに注意すること。
0262245NGNG
>>254
aは配列オブジェクトですよね。
型でいうとint [2][3]です。つまりサイズは24バイト。
&aは配列全体へのポインタで(ANSI規格より)、型は
int (*)[2][3]ですよね。ポインタなんだから、double d
に対するsizeof(&d)と同じく4バイトが正しいと思うんです。

>>255
なんか正しそう。なんて本ですか?

>>256,257
単なる興味だけです。。どうも気持ち悪くて。
0263デフォルトの名無しさんNGNG
配列全体のアドレスっつうのは、範囲ということなのか?
026411NGNG
>>262
>&aは配列全体へのポインタで(ANSI規格より)、型は
>int (*)[2][3]ですよね。ポインタなんだから、double d
>に対するsizeof(&d)と同じく4バイトが正しいと思うんです。

よしよし、同志だな。ただdouble*とint(*)[2][3]の
サイズが同じだとはどこにも決まっていないな。
問題はtypeid(a)==typeid(&a)なことだ!!
0265デフォルトの名無しさんNGNG
動的に二次元配列もどきをつくるとき、いったんポインタの1次元配列を
つくるよね。
静的な配列にも概念的にはこれが存在するが、その実装はコンパイラ依存だし
直接アクセスすることもできないから、Cでは今回の件に関して
このような仕様になっているんじゃないの?
026611NGNG
>>263
具体的にアドレスが何なのかは処理系依存だったと思う
0267245NGNG
>>258
gccが正しいのかな?それだと何も疑問無いんだけどな。

>>255
int a[2][3]; --> int [2][3]型 -->配列全体のサイズ
int *a[2]; --> int* [2]型 -->ポインタ二つ分のサイズ
int **a; --> int **型 -->int*へのポインタのサイズ
int (*a)[3]; --> int (*)[3]型 -->配列へのポインタのサイズ

cout << sizeof(int [2][3]) << endl;
cout << sizeof(int* [2]) << endl;
cout << sizeof(int **) << endl;
cout << sizeof(int (*)[3]) << endl;
と明示的に型指定すると24,8,4,4と出るなあ。
これは納得。bcc5.5.1です。
0268254NGNG
>>262=245
>...と同じく4バイトが正しいと思うんです。
思うんですとか言われても現実にはsizeof(&a)=24という
腐った仕様が厳然と存在してしまっている。
君の取るべき道は三つだ。
・そういうものかと納得する。
・あきらめてC/C++をやめる。
・憶測や妄想を捨て作者に歴史的経緯を聞いてここで報告する。
0269デフォルトの名無しさんNGNG
気持ちはわからんでもないが、正直どうでもいい話だ。
0270245NGNG
>>264
>ただdouble*とint(*)[2][3]の
>サイズが同じだとはどこにも決まっていないな。
>問題はtypeid(a)==typeid(&a)なことだ!!

そうなんです。
027111NGNG
>>268
設計者のミスに違いない!!!
次のバージョンに期待
0272245NGNG
>>268、>>269
その仕様が言語仕様なのか処理系依存なのか
分かればスッキリするんですが。

・見なかったことにします。
皆さん忘れてください。
0273デフォルトの名無しさんNGNG
仮想関数のアドレスを表示しようとすると "1" としか表示されない
のですが、なぜでしょうか?

class A {
public:
virtual void print() const { cout << 10 << endl; }
};

class B : public A {
public:
void print() const { cout << 20 << endl; }
};

int main()
{
typedef void (A::*afunc)() const;

cout << "A::print = " << hex << (afunc)A::print << endl;
cout << "B::print = " << hex << (afunc)B::print << endl;
}
0274デフォルトの名無しさんNGNG
>>272
言語仕様。
0275デフォルトの名無しさんNGNG
>>273
A::printってなによ?非staticでしょ?
027611NGNG
>>272
int a[2][3];
について
int (*p)[2][3]=&a;
が可能であるが、
array to pointer conversionではint[2][3]はint(*)[3]へ
変換されるはずだから、typeid(a)==typeid(&a)だとすると
上のはおかしい。つまり変換(standard convertion)は行われていない。
そこで&aはsizeof(&a)でもtypid(&a)でも式でもint(*)[2][3]となるはず。
だから(typeid(a)==typeid(&a)が)ANSIから外れているのはまず間違いない。
0277デフォルトの名無しさんNGNG
>>275
うーんメンバ関数のアドレスを表示したいんです。
例えば

A aa;

としておいて、

(aa.*a)(); とすれば、"a"、つまり10が表示されます。関数を呼び出す
のではなく、関数のアドレスを表示したいのです。
0278デフォルトの名無しさんNGNG
>>277
((char*)aa + (char*)&A::print)
0279デフォルトの名無しさんNGNG
>>278
エラー E2031 virtual.cpp 20: 'void (A::*)() const' から 'char *' へのキャストはできない(関数 main() )
と出てしまいました。
0280245NGNG
>>276
確かに、
int (*p)[2][3]=&a; で
sizeof(p)は4を返しますからね。
0281デフォルトの名無しさんNGNG
>>277
メンバ変数なら0からキャストするとして、メンバ関数は無理じゃないの?
ましてや仮想関数だし
0282デフォルトの名無しさんNGNG
>>279
&aa
0283デフォルトの名無しさんNGNG
>>281
ということは、メンバ関数のアドレスを取って呼び出すことは可能でも、
メンバ関数のアドレスを表示することは不可能ということなのでしょうか。

仮想関数でなくしても(virtualを取っても)、やはりできないようです。
0284デフォルトの名無しさんNGNG
>>282
(char *)&aa + (char *)&A::print としても同じエラーが出ます。
0285デフォルトの名無しさんNGNG
reinterpret_cast<A*>(0)->print
は?
028611NGNG
>>283
ど〜よ
class A{
public:
virtual void foo(void) {}
} ;
main(){
void (A::*t)(void)=&A::foo;
void *p=&t;
cout<<hex<<*(int*)p<<endl;
}
0287デフォルトの名無しさんNGNG
>>285
だめみたいです。やはり無理みたいです。
エラー E2094 virtual.cpp 24: << 演算子が使われたがクラス ostream では void (* (_closure )())() 型のための定義が存在しない(関数 main() )
0288デフォルトの名無しさんNGNG
>>287
printf("%xで出すのはどうだい?
0289デフォルトの名無しさんNGNG
>>286
うまくいきました!どうやら、メンバ関数のポインタは、一度 void * に
代入して、コンパイラを騙してから、アドレスを見る必要がありそうですね!
0290デフォルトの名無しさんNGNG
>>288
それでもうまくいきました。つまり、出力演算子 << が対応してないための
ようです。
029111NGNG
ちと冗長だった
class A{
public:
virtual void foo(void) {}
} ;
main(){
void (A::*t)(void)=&A::foo;
cout << hex << *(int**)(void*)&t<<endl;}

>>288
その手があったか
0292デフォルトの名無しさんNGNG
>>291ありがとうございます。
cout << hex << *(int*)(void*)&t<<endl;} でもいいようですね。
0293デフォルトの名無しさんNGNG
もっと単純にしてもよい。
cout << hex << *(unsigned*)&t<<endl;
029411NGNG
>>292
サイズが同じ型なら何でも。思いっきり処理系依存だけども
ただ、これがメンバ関数へのアドレスであるという保証はどこにも…
ビットパターンがそうだというだけで
029511NGNG
>>293
あちゃ〜〜、下手うった
0296デフォルトの名無しさんNGNG
>>294
そうですね。手持ちの本「C++標準ライブラリ」で、Cの "%p" に当たる
出力方法を探してみましたが見つかりませんでした。

処理系依存にならない方法があればいいのですがわかりません。
C++の内部のメカニズムをいじくり回すようなプログラムは書きにくく
なっているのかな。
0297デフォルトの名無しさんNGNG
>>296
つーか、"%p"自体が元々処理系依存。
029811NGNG
処理系依存はsizeof(void(A::*)(void))と
*(T*)&tのsizeof(T)を一致させる話ね。いちおう
0299デフォルトの名無しさんNGNG
>>255 の本だけど
エキスパートCプログラミング 知られざるCの深層 アスキー出版

面白い本だけど、今回の問題はコラム扱いで >>255以上の事はあまりのってない
立ち読みするなら P261 だ
0300デフォルトの名無しさんNGNG
>>255 の本に以下のような記述あり

次のような配列への参照は、最初の要素へのポインタに自動では置き換えられない
1sizeof()の中の配列
2&演算子によって配列のアドレスが取得される場合
3配列が、初期化に使われる文字列リテラル、またはワイド文字列リテラルの場合
0301デフォルトの名無しさんNGNG
cout << sizeof("テストだゴルァ") <<endl;
cout << sizeof(&"テストだゴルァ") <<endl;

両方とも 同じ結果です
0302300NGNG
ガイシュツでした スマソ
0303デフォルトの名無しさんNGNG
245の質問自体が112あたりの外出
0304245NGNG
>>299
どうもです。今度見てきます。
0305デフォルトの名無しさんNGNG
http://www.bohyoh.com/CandCPP/FAQ/FAQ00084.html
this.じゃなくて、this->とか(*this).じゃないと駄目だよなぁ…。
でもメール受け付けてないし、直りそうに無いな。。
0306デフォルトの名無しさんNGNG
C++とC言語ってどこがどう違うんですか?
0307デフォルトの名無しさんNGNG
いやーC++最高
生産性が高くなるし、コードは簡潔で見易くこの上ない
0308デフォルトの名無しさんNGNG
>>300や>>261が正しいとすると、
&aで配列全体のアドレス(ポインタ)になって、sizeof(&a)で、
int (*p)[2][3]=&a;sizeof(p);になって結局4になるのが
正しいように見えるけど?
&aと書いた時点で、それはもう配列じゃなくて配列へのポインタ
に変わってしまってるわけだから、>>300の1番目の規則は
適用できないはず。

配列全体のサイズを返してしまう処理系が間違ってるか、もしくは
本の記述が間違ってるとしか考えられない。
0309デフォルトの名無しさんNGNG
>>308
2番目の規則が適用されるんじゃないの?
0310308NGNG
&aのaは2の規則により特別に配列だけど、&aの返す値はアドレスってことね。
その値をsizeofに渡してるわけだから1の規則はあてはまらない。
1はアドレスじゃなくて配列の名前を渡した時だから。
0311308NGNG
>>309
二番目の規則が適用されるのはわかってるけど、
それでも1が無いとsizeofの値は4になるはずだと思うんだが。
0312デフォルトの名無しさんNGNG
>>310
1はsizeof()の中の配列とかいてあるだけで、名前で渡すとか、
アドレスで渡すとか書いてないよ
0313308NGNG
>>312
いや、でも「配列へのアドレス」はポインタとは言えるかもしれないが、
配列じゃないだろ。
>>261のURL見ても、a[10]のaのことを配列と言ってるようだし。
まず、この場合は4にならなくちゃおかしい。

それで、「配列への参照」とは言えるかも知れない。だから、>>300
の方はあってるかもしれない。
でもそうなるとint (*p)[2][3]=&a;sizeof(p);だって、配列全体
の大きさにならなくちゃおかしい。これだって「配列への参照」だから。
でも過去レスでは4になったと言っている。
となると、結局どっちにしろ駄目だと思うんだが…
0314デフォルトの名無しさんNGNG
>>313
pはポインタだろ。配列の先頭を指す
0315308NGNG
>>314
そう思うよ。だけど、&aだってそうだろ。
0316デフォルトの名無しさんNGNG
>>315
pは左辺値になりうる。
&aは左辺値じゃないだろ?
別物だよ
0317308NGNG
>>316
まあそうだな。
だったら、左辺値のポインタならポインタのサイズになって、右辺値の
ポインタならsizeofは配列全体を返すというべきだ。
それなら、つじつまが合う。
でもそうだとすると>>300と>>261の記述は間違ってるぞ。
右辺値とか左辺値とか言ってない。そもそも「右辺値のアドレス」には
変換されないと言ってるように感じられる。
0318デフォルトの名無しさんNGNG
>>317
左辺値の話は、あなたが
>そう思うよ。だけど、&aだってそうだろ
と書き、pと&aを同一視しようとしたから書いただけ。
0319308NGNG
>>318
そう思ったのなら、俺の言い方が悪かったかな。
どちらもポインタではあるといいたかっただけ。

俺が一番問題にしたいのは、本の記述と処理系の動作が違ってるのでは
ないかということ。
0320デフォルトの名無しさんNGNG
>どちらもポインタではあるといいたかっただけ
&aはポインタであると確定しているの?
0321308NGNG
>>320
少なくとも「アドレス」とは言ってるな。あと、>>261のリンク先では
&a[0]等、「&なになに」をポインタと言ってる。
それに、「配列はポインタに置き換えられる」と言ってる場合のポインタは
右辺値のアドレスじゃないとおかしい。a[10]の時のaは左辺値では無いから。
0322デフォルトの名無しさんNGNG
ポインタの実装に関する規定は何ら無く、多くの処理系では直接アドレスを
割り当てているだけでは?つまり処理系依存
0323308NGNG
>>322
その件はまた一つの議論になるし、処理系依存でも俺はアドレスと言ってしまっていいと思うが、
ここではそういう議論は置いといて、便宜上「アドレス」と読んで話しをすすめれば
いいんじゃないかな。>>261もそうしているようだし。
0324デフォルトの名無しさんNGNG
>>323
いいんじゃない?
0325デフォルトの名無しさんNGNG
どうした?つづけてください。
(長文かいていたらすまそ)
0326308NGNG
とりあえず、俺は言いたいことは言ったよ。
俺の中では記述と現実が食い違ってるって結論だから、
返事待ち。
0327デフォルトの名無しさんNGNG
323で話を切ったのはそっちだよ。
俺の中では処理系依存である部分の違いを細かく追及することが無意味だって
結論です。
0328308NGNG
>>327
だから、その話は関係ないのでは?それは表現の問題で、
>>300と>>261はその問題を無視し(あるいは無視せず)、アドレスとして
話しを進めている。だから、それにのっとてここではポインタはアドレスと
して話を進めればいいのではないかって俺は言ってる。
で、sizeofの返す値の問題はまた別の問題だ。
0329デフォルトの名無しさんNGNG
この件について、配列のアドレスとポインタの関係は中核なんだが。
あなたが納得できない理由がそこにある。
0330デフォルトの名無しさんNGNG
fjくさいな
0331デフォルトの名無しさんNGNG
おわったか。
■ このスレッドは過去ログ倉庫に格納されています