C言語なら俺に聞け(入門編)Part 63at TECH
C言語なら俺に聞け(入門編)Part 63 - 暇つぶし2ch255:デフォルトの名無しさん
10/04/18 23:21:55
>>253
gccは特にinlineを無視する確率高いよね

256:デフォルトの名無しさん
10/04/18 23:26:24
人間よりもコンパイラの方が大概うまくやってくれる

257:デフォルトの名無しさん
10/04/18 23:28:44
>>256
しかしそのコンパイラを作っているのは人間である。

258:デフォルトの名無しさん
10/04/18 23:30:35
コンパイラのかなりの部分は自動生成されるコードだけどな。

259:デフォルトの名無しさん
10/04/18 23:30:47
>>257
ゲームの人工知能と同じ

260:デフォルトの名無しさん
10/04/18 23:48:54
このまえVC++で、逆アセンブルしてコードみてみたら、
こんな関数までインライン展開すんのかってびっくりした。

261:デフォルトの名無しさん
10/04/19 01:36:21
淫乱関数か。

262:デフォルトの名無しさん
10/04/19 01:37:10
>>250-254
ありがとうございます!
もうちょっと自分で調べて勉強してきます。

263:デフォルトの名無しさん
10/04/19 02:15:31
>>257
同じ人間と思うなよ
コンパイラ作ってるやつは底辺プログラマーよりずっと優秀なんだから

264:デフォルトの名無しさん
10/04/19 02:43:42
>>263
あいつらは宇宙人だから。

おっと、宇宙人と言ってもルーピーは第9地区行きだからな。

265:デフォルトの名無しさん
10/04/19 19:17:54
>>248

266:デフォルトの名無しさん
10/04/19 19:19:54
>>253
inlineは同じ翻訳単位内に書かれないといけないので
inline書かずに同じ事しようと思うと
staticにしないといけなくなるぜ

267:デフォルトの名無しさん
10/04/19 22:23:52
for文内で作ったオブジェクトを全て選択するにはどうしたら良いですか

268:デフォルトの名無しさん
10/04/19 22:51:57
ポインタstartが指してるところから、ポインタendが指してるとこの「間」の文字列を
dataに格納するにはどうしたらいいですか

目的としてはhtmlのタグ取って特定のタグで囲まれてる文字列を抜き出したいんです

269:デフォルトの名無しさん
10/04/19 22:56:08
>>268
sprintf(data, "%.*s", end-start, start);

270:デフォルトの名無しさん
10/04/19 23:37:48
>>269
それっぽいのができました、どうも

fprintfでやったらポインタじゃダメだって怒られたのに、
sprintfだとできるのね

271:デフォルトの名無しさん
10/04/19 23:42:42
>>268
俺だったら正規表現が使える言語に逃げちゃいそうw

272:デフォルトの名無しさん
10/04/19 23:46:05
正規表現は外部ライブラリで補完できるんじゃないの?

273:デフォルトの名無しさん
10/04/20 00:41:09
>>270
> fprintfでやったらポインタじゃダメだって怒られたのに、
ここら辺が特に理解できない

274:デフォルトの名無しさん
10/04/20 00:48:12
fprintf(filep, end-start, start);
な感じでやってみたら、
3番目のargumentはポインタじゃincompatibleだぜ
ってエラーが出た

275:デフォルトの名無しさん
10/04/20 01:47:17
何でそういう変な訳にしたのかわからんが、それだと
2番目の引数ありえんワロス
ってエラーが出ないか?


276:デフォルトの名無しさん
10/04/20 02:42:10
#include <stdio.h>
#include <string.h>

int main( void )
{
char source[256];
char value[256];
int i,j, k = 0;
strcpy( source, "<name>2ch C言語スレ</name>" );
/* ヌル文字まで走査を続ける */
for( i = 0; i < 256 || source[i] != '\0'; i++ ) {
/* 開始タグを検出 => 次の文字が「/」ではない */
if( source[i] == '<' && source[i+1] != '/' ) {
/* 「>」が検出されるまで1文字ずつ調べる */
for( j = ++i; source[j] != '>'; j++ );
i = j;
}
/* 終了タグ検出 => 「<」の次が「/」*/
else if( source[i] == '<' && source[i+1] == '/' ) {
/*それ以上操作する必要がないのでループを抜ける */
break;
} else {
/* 終了タグが検出されるまで、結果保存用配列へ1文字ずつ格納 */
value[k++] = source[i];
}
}
/* ヌル文字挿入(文字列として成立させる為) */
value[k] = '\0';
printf( "対象文字列:%s\n", source );
printf( "抽出文字列:%s\n", value );
       return 0;
}

277:デフォルトの名無しさん
10/04/20 02:43:05
20分くらいで書いたが、sprintf()でやる方が頭を悩ませた。

278:デフォルトの名無しさん
10/04/20 11:17:59
タグを消すだけならこれでもおk
#include<stdio.h>
#include<string.h>

int main(void)
{
char source[256];
char value[256]="";
char *p, *q;

strcpy(source, "<name>2ch C言語スレ</name>dummy string<br><br>");
strcpy(value, source);

for(p=value;(p=strchr(p, '<'));)
{
q=strchr(p+1, '>');
if(q==NULL) break;

memmove(p, q+1, strlen(q+1)+1);
}

printf( "対象文字列:%s\n", source );
printf( "抽出文字列:%s\n", value );

return 0;
}

279:デフォルトの名無しさん
10/04/20 11:32:01
sprintf を使ってみた
#include<stdio.h>
#include<string.h>

int main(void)
{
char source[256];
char value[256]="";
char *start, *end, *dest=value;

strcpy(source, "hello<name>2ch C言語スレ</name>dummy string<br><br>");

for(start=source;(end=strchr(start, '<'));)
{
dest+=sprintf(dest, "%.*s", end-start, start);
start=strchr(end+1, '>');
if(start==NULL) break;
start+=1;
}
if(start) sprintf(dest, "%s", start);

printf( "対象文字列:%s\n", source );
printf( "抽出文字列:%s\n", value );
return 0;
}

280:デフォルトの名無しさん
10/04/20 18:45:20
ヘッダに計算書くっていうプログラムなんだがわかる人いる?
ポインタを応用してヘッダファイルとソースファイル2つ使うらしい

簡単な足し算みたいなんだけどわからん

281:デフォルトの名無しさん
10/04/20 19:07:02
>>280
わかるよ

282:デフォルトの名無しさん
10/04/20 19:43:26
ヘッダファイルに計算する関数を書いておくとか?

283:デフォルトの名無しさん
10/04/20 20:24:07
>>280
日本語でおk

284:デフォルトの名無しさん
10/04/21 00:31:15
URLリンク(ux.getuploader.com)
これの表示するフォントを変えたいと思うのですが僕にはレベルが高すぎでした ゲームの中文化ランチャーで少々いじると日本語化できるようになります。どこでフォントを指定しているのでしょうか。解析お願いします。

285:デフォルトの名無しさん
10/04/21 13:45:26
板違い

286:デフォルトの名無しさん
10/04/21 18:57:30
Cの入門書を読んで
標準関数とWinsckを使いプログラミングできるようになしました。

この次の段階としてはどのような学習をすればいいでしょうか?
ゲームなどは作るつもりありません。
私がやりたいことは画像処理(OCR系の画像解析)や
ネットワーク通信(自分パソコンと友達のパソコンで通信するよなの)を
作りたいと思ってます。
ネットワーク通信はWinsockをもっと勉強すればいいかな?と思いますが、
画像処理などはどうなんでしょう?

287:デフォルトの名無しさん
10/04/21 19:03:55
>>286
パソコン通信()

288:デフォルトの名無しさん
10/04/21 19:11:25
>>286
とりあえずぐぐってみた?
ある程度それで概要をつかむほうがいいと思う

289:デフォルトの名無しさん
10/04/21 19:11:43
>>287
パソコン通信ですか・・・
それはWinsockとは違うのですか?

290:デフォルトの名無しさん
10/04/21 19:14:04
>>286
>ネットワーク通信はWinsockをもっと勉強すればいいかな?
Winsockの基本さえわかれば、
(自分パソコンと友達のパソコンで通信)程度なら作れるはずだよ。
作ればいいだけ。

>画像処理などはどうなんでしょう?
特に何も必要でないよ。すぐに作ればいいんじゃない。
OCRなら大した知識などなくてもすぐに作れるよ。

少しぐらいは自分の頭で考えようよ。

291:デフォルトの名無しさん
10/04/21 19:16:00
>>290
> OCRなら大した知識などなくてもすぐに作れるよ。
OCRがすぐ作れるって?
お前すごすぎだろ

> 少しぐらいは自分の頭で考えようよ。
それはまあごもっとも。


292:デフォルトの名無しさん
10/04/21 19:21:00
>>290
ありがとうございます。

OCRって簡単なんですか・・・
頑張って作ってみます。

293:デフォルトの名無しさん
10/04/21 19:28:46
>>291
OCRって言ってもピンきりだろ。そりゃ製品レベルは無理に決まってる。

けど、例えば数字に限定したものとか、
ベクターでなくビットマップベースにするとか、
そういう限定があればすぐに作れるだろ。

最初はそれでいいんだし、そこから改良を加えていけば幾らでも認識率は高くできる。

294:デフォルトの名無しさん
10/04/21 19:33:06
>>293
jpgファイルとかで最初は英数字だけの解析をしたいのです・・・
なにを勉強すればいいですか?
ホントに入門書上がりで最近やっとWinsockでFTPやPOP、HTTP通信が
できるようになってきたひよっこです・・・

295:デフォルトの名無しさん
10/04/21 19:46:54
統計とかパターン認識とか
高級なことをしたいならウェーブレット変換とかで特徴抽出できる
簡単にやりたいならOpenCVでできる、まぁ原理が知りたければSIFTとかSURFとかの論文読めばいいよ
SIFTとか特許があるから気を付けてね

ネットワーク関係は専門じゃないので詳しくは知らない
トランスポート層しか扱ったこと無いので、詳しくは他の人頼む

296:デフォルトの名無しさん
10/04/21 20:29:38
次は画像フォーマットを知ることじゃないの?
ビットマップは単純だからビットマップからはじめると良い。
ビットマップ画像を読みこんで白黒化して出力するツールをつくれ

297:デフォルトの名無しさん
10/04/21 20:44:16
>>295
ありがとうございます。
論文って苦手なんですけど、
やっぱり避けて通れないのですね・・・


>>296
わかりました。
ビットマップ画像から作成してみます。
ライブラリはDXでいいですよね?

298:デフォルトの名無しさん
10/04/21 21:08:04
Cの標準ライブラリだけで十分。コンソールで良い。

299:デフォルトの名無しさん
10/04/21 21:15:20
そもそも行列とかフーリエ変換とかしってるのかな?


300:デフォルトの名無しさん
10/04/21 21:17:00
応用代数学勉強すればいいと思うよ
画像処理アルゴリズムとかそのものずばりの本もあるし。
学校行っていないのならデジタル画像処理とかの資格試験勉強すればいいんで内科医?


301:デフォルトの名無しさん
10/04/21 21:19:16
国家資格は年2回試験があるから挑戦したら?
自信あるなら2級当たりから始めるといいかもシレン
3級は基礎知識だから名

302:デフォルトの名無しさん
10/04/21 22:59:49
国家資格ですか・・・
基本情報技術者なら午後の選択C言語で取りました。
19年度の春試験。

303:デフォルトの名無しさん
10/04/21 23:07:25
>>300
でもずばり jpg を説明した書籍となるといいのがみつからないなあ。
URLリンク(www.amazon.co.jp)
これの第一版はもっている、もっているだけやけど。

304:デフォルトの名無しさん
10/04/21 23:43:40
>>303
俺はその本でJPEGのエンコード・デコードは実装できたなー。
DCTとか概念的なところは「これならわかる!応用数学教室」(だっけ?)が分かりやすかった。

305:デフォルトの名無しさん
10/04/22 00:10:14
#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <stdlib.h>
#include <wchar.h>
main(){
wchar_t kana[] = L"あいうえおかきくけこ";//---1
setlocale(LC_ALL, "");
printf("kana::%ls\n", kana);
printf("kana[2]::%lc\n", kana[2]);
wchar_t wbuf[81], *p1;//----------------------2
printf("enter wide_byte character::\n");
fgetws(wbuf, sizeof wbuf, stdin);
if((p1 = wcschr(wbuf, '\n')) != NULL)
*p1 = L'\0';
setlocale(LC_ALL, "");
printf("wbuf_no_naiyou::\n");
printf("%ls\n", wbuf);
printf("wbuf[2]::%lc\n", wbuf[2]);

return 0;
}

306:305
10/04/22 00:12:58
windows上bccで、日本語文字列の入力を配列に受け取って、その要素にアクセスするのが目的です。

1既存のワイド文字列へのアクセス
ができたので、
2ワイド文字列の入力を受けてその要素へのアクセス
をしようとしたのですが、fgetwsに1byte文字を入力したときはうまくいくのに、
ワイド文字を入力するとfgetwsのエコーバックが見えるところで止まってしまいます。
どうしたらいいでしょう?みかか変換プログラムを書いてみようと思ったのです。


307:デフォルトの名無しさん
10/04/22 00:23:25
画像処理の資格はこれでしょ
CG-ARTS協会|2010CG検定
URLリンク(www.cgarts.or.jp)
これを3級から始めれば高校生程度の学力から初めても大丈夫


308:デフォルトの名無しさん
10/04/22 00:28:06
>>306
cじゃなくてrubyでやったら?
Cじゃなきゃいけない理由って何?

309:デフォルトの名無しさん
10/04/22 00:28:36
宗教上の理由からです

310:デフォルトの名無しさん
10/04/22 00:29:17
>>297
ライブラリ使うんなら別にどの形式からでもいいよ
ファイルフォーマットを知る必要もたいしてなかろ

311:デフォルトの名無しさん
10/04/22 00:37:41
へえ

312:デフォルトの名無しさん
10/04/22 01:06:51
ウヒヒ

313:デフォルトの名無しさん
10/04/23 08:37:56
>>306
Microsoftでやったら?
bccじゃなきゃいけない理由って何?

314:デフォルトの名無しさん
10/04/23 14:25:37
intの2次元配列を使いたいのですが、int hoge [作りたい数]「ここ」←ここはなにを表してるのですか?
charならバイト数だと思うのですが、intはバイト数が決まってたと思うのですが
作りたい数までの各番号に対応したintを取り出したいのです

315:デフォルトの名無しさん
10/04/23 15:03:35
>>314
お前がいうところの2次元配列ってなんだ?

世間では要素が n 個の配列(1次元配列)は hoge[n] であり、
要素が n x m 個の配列(2次元配列)を hoge[n][m] で表す。

1次元で足りるなら1次元配列を使え。

316:デフォルトの名無しさん
10/04/23 15:03:44
それなら1次元配列でよくね?

317:デフォルトの名無しさん
10/04/23 15:05:53
つまりint hoge[作りたい数]でいけるってことですか。
そういう使い方を全然知りませんでした。ありがとうございました

318:デフォルトの名無しさん
10/04/23 15:06:33
>>314
int hoge[3]; はintが3個並んでる。
int hoge[3][4]; はintが4個並んだものが3個並んでる。
hoge[0][0], hoge[0][1], hoge[0][2], hoge[0][3], hoge[1][0], hoge[1][1], ... の順で。

intのバイト数は規格で固定されてはいない。
実際にコンパイルする時にその環境で何バイトになるのかはそりゃ決まってるけど。
今はPCの環境だとほとんど4バイト。

319:デフォルトの名無しさん
10/04/23 15:16:51
charでバイト数を指定して2次元配列、か。
それはたぶん文字列の配列を作ろうとしていたんじゃないかな。

320:デフォルトの名無しさん
10/04/23 18:05:22
C言語でシーザー暗号の解読プログラムを作っています。
手順としては、暗号化された文字列を入力して1つずつ文字列をずらして
26通りの文字列を出力するプログラムです。

#include<stdio.h>
int main(void)
{
char ang[8]; //今回は最大8文字の文字列
int i,j;

for(i=0;i<26;i++){
for(j=0;j<8;j++){
printf("%c",ang[j]+i);
}
}

初めはASCIIコードのZとaが繋がっているものと思いこう組んだら
Zの後には記号が入っていて詰まってしまいました。
A-Zまでの配列を作ってその中で回す、とかASCIIコードでもZの次をAにする
とか色々考えましたが、どうしていいのかが分からないです…。

ご指導お願いします。

321:デフォルトの名無しさん
10/04/23 18:10:44
(ang[j] - 'A' + i) % 26 + 'A'

322:デフォルトの名無しさん
10/04/23 18:28:17
>>320
isalpha()

323:デフォルトの名無しさん
10/04/23 18:37:27
>>320
本題とは関係ないが、
>char ang[8]; //今回は最大8文字の文字列
ang[8]だと最大7文字の文字列な

324:デフォルトの名無しさん
10/04/23 18:41:29
NUL終端文字列とは言ってないので、間違っていない
それにprintf("%c",ang[j]+i);だから、NULは必要としていないと読める

325:デフォルトの名無しさん
10/04/23 18:50:38
ポインタ無隋って聞いたけど
C言語の入門書とかに書いてるような小さいサンプルコードだと
全然難しくなくて何が難しいのかわからなかった。

ポインタってなんかむずかしい部分あるの?

326:デフォルトの名無しさん
10/04/23 18:51:26
NUL終端w

327:デフォルトの名無しさん
10/04/23 18:53:34
分かる人には難しくない、分からない人には難しい。
慣れればどうってことはない。

328:デフォルトの名無しさん
10/04/23 19:00:50
>>325
入門編が難しいはずない。

329:デフォルトの名無しさん
10/04/23 19:04:05
初心者は、LinkedListを自前で実装してみ?って言われて初めて、
自分がポインタを理解していないことに気づくもの。

330:デフォルトの名無しさん
10/04/23 19:07:33
>>325
人によるんじゃない?
俺は関数ポインタの理解が遅かったけど、いざ理解したらなにが難しかったのか分からなくなったな

331:デフォルトの名無しさん
10/04/23 19:11:03
何も有益な情報は残さずに読むものを不快にさせるだけのレスをするやつは死ねばいいのにな

332:デフォルトの名無しさん
10/04/23 19:12:48
int (*(*foo)(int (*(*)(void))(void)))(int (*)(void))

333:デフォルトの名無しさん
10/04/23 19:13:21
俺は死ねばいいとか思わないけど、なんで>>331は自殺しないの?

334:デフォルトの名無しさん
10/04/23 19:20:08
ポインタと配列がごっちゃになってしまうところ
ある配列の実要素が ポインタである(ポインタ配列)場合 配列である(2次元配列)場合
各それぞれで、記憶領域の配置が本質的に違うのに理解できるまでの敷居が高い。

既に書かれている記述を読むのは可能でも
やりたいことを実装するのに、どちらが適切かを選択できるか がキーポイント

335:デフォルトの名無しさん
10/04/23 19:21:54
関数の引数や戻り値にポインタ変数が使われる場合なんかも初心者は混乱しやすいな

336:デフォルトの名無しさん
10/04/23 19:24:36
次元配列って

□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□
□□□□□□□□□

こんな感じで
配列の実要素がポインタってのは

□→□□□□□□□□□
□→□□□□□□□□□
□→□□□□□□□□□
□→□□□□□□□□□
□→□□□□□□□□□

こういうこと?

337:デフォルトの名無しさん
10/04/23 19:30:14
>>336
おおよそ yes
指している先がどれだけの大きさの器があるか未確定 & ほとんど知る術は無い
(さらに、不正な場所を指している可能性もあるん)

□→□□□□
□→□□□□□□□
□→□
□→ぬるぽ!
□→鼻から悪魔

こういうことがあり得る

338:デフォルトの名無しさん
10/04/23 19:34:43
>>321
割った余りで考えるという思考がありませんでした…。
ありがとうございました!

>>322
真偽でif文作るってのがあるのを知りませんでした。
勉強になりました!

339:デフォルトの名無しさん
10/04/23 21:27:13
>>332
これ関数ポインタ?

DLLの関数を動的に呼ぶときに、
GetProcAdress()で関数ポインタ取ってくるくらいしか使い道が分からん。

340:デフォルトの名無しさん
10/04/23 21:38:28
分かりやすそうなところを選ぶとしたらイベントハンドラとかかな。

341:デフォルトの名無しさん
10/04/23 22:14:53
>>339
引数を取らず引数を取らずintを返す関数へのポインタを返す関数へのポインタを取り、
引数を取らずintを返す関数へのポインタを取りintを返す関数へのポインタを返す関数
へのポインタだね。

342:デフォルトの名無しさん
10/04/23 22:27:42
ええい、いいから黙ってtypedefしろ

343:デフォルトの名無しさん
10/04/23 22:35:09
typedefしまくりで夢がひろがりんぐ

344:デフォルトの名無しさん
10/04/23 23:21:31
URLリンク(kansai2channeler.hp.infoseek.co.jp)

番号と名前がランダムに記入されたテキストを読み込んで、数字と名前に分けて配列に格納し、番号昇り順で並べかえてテキストファイルで出力したいのですが
並べかえがうまくいきません
とりあえず作ってみたのですが…
アドバイスください

345:デフォルトの名無しさん
10/04/23 23:26:57
>>344
tmp はいらない
ソートができていない
ソートが終わってから出力すればいい

誰かに写させてもらったの?

346:344
10/04/23 23:33:00
過去に作ったやつを何個か組み合わせて作ってたらこうなりました…

347:デフォルトの名無しさん
10/04/23 23:33:07
>>344
番号、名前、テキストの定義をすると話が早いと思う。

例:
番号は、'0'から'9'の文字からなる文字列
名前は、ひらがな、かたかな、漢字からなる文字列
テキストは、番号と名前をスペースからなる文字列で、最後以外の番号および名前の後には必ずスペースが来る。

11113 3333 5892739 山田 12128384 高橋 32939 8883 細川 32932399

とか。

348:デフォルトの名無しさん
10/04/23 23:37:36
>>344
ヒント
for
    fscanf

for
    for
        if

for
    fprintf

349:デフォルトの名無しさん
10/04/23 23:41:59
>>344

まず

 1.ファイルを全部読む
 2.並び替えを行う
 3.並び替えたデータをファイルに書く

っていう流れに書き換えて
2.の部分をじっくり考えてみてください。

350:349
10/04/23 23:43:51
>>348
もろかぶったスマンw

351:デフォルトの名無しさん
10/04/24 00:47:16
関数から構造体を返す必要がある場合、何か基準や定石はありますか?
こういう時にはこうすれば良いという指針があれば知りたいです。

//構造体の例
struct my_struct {
 int size;
 void *ptr;
 int data[];
};

//(1)create関数の中で構造体をmallocして、delete関数の中でfreeする。
struct my_struct* create_my_struct(int param);
void delete_my_struct(struct my_struct* md);

//(2)呼び出し元で構造体を確保して、init関数の中でメンバーをmallocして、release関数の中でメンバーをfreeする。
// 構造体そのものは呼び出し元でどうにかする。
int init_my_struct(struct my_struct* md, int param);
void release_my_struct(struct my_struct* md);

それぞれ下記のデメリットがあると思います。

(1)のデメリットは呼び出し元で入れたいメモリー領域がある場合、createした構造体をコピーする必要がある。
(2)のデメリットは呼び出し元でinitを呼ぶ前に構造体の大きさを知っていなければいけない。

352:344
10/04/24 00:55:12
皆さんのアドバイス通りに流れを考えて、いちからやり直したら無事成功しました。
ありがとうございました。

353:デフォルトの名無しさん
10/04/24 01:20:37
>>351
(1)のデメリットがよくわからんな
そのメモリ領域ってのは create で確保するんじゃないの?
あとコピーうんぬんはコピー用の関数でOK?


354:デフォルトの名無しさん
10/04/24 01:51:37
>>353
実装はこんな感じです。

struct my_struct* create_my_struct(int param)
{
 struct my_struct* md = (struct my_struct*)malloc(sizeof(struct my_struct) + sizeof(int)*param);
 md->size = param;
 md->ptr = malloc(param);
 return md;
}

void delete_my_struct(struct my_struct* md)
{
 free(md->ptr);
 free(md);
}

デメリットは、下記のような場合、memcpyが必要なことです。

int get_data(char* buf, int size)
{
 struct my_struct* md = create_my_struct(size);  //←ここでbufを渡せたら
 int ret = memcpy(buf, md->ptr, size);         //←ここでコピーしなくていい
 delete_my_struct(md);
 return ret;
}

355:デフォルトの名無しさん
10/04/24 02:02:09
なんか違和感があるな。どういう思想なんだろ

356:デフォルトの名無しさん
10/04/24 02:49:32
>>354
*ptrの使い道はなんだろ。つーか、メンテしやすさ重視ならこうじゃね?


typedef struct {
 int size;
 int chinko;
 int unko;
 int data[];
} unko_t ;

unko_t *create_unko( unko_t *md, char *buf, size_t size )
{
 md = malloc( sizeof(unko_t) + sizeof(int)*size );
 if(md){
  md->size=size;
  memcpy(md->data,buf,size);
 }
 return md;
}

int get_data(char *buf, int size)
{
 unko_t *md;
 if( create_unko( md, buf, size )==NULL ) perror("unko");


357:デフォルトの名無しさん
10/04/24 02:50:30
途中で送信しちゃったよもうどうでもいいや

358:デフォルトの名無しさん
10/04/24 02:58:38
>>354
まぁよくわからないんだけど、こんな感じにすればOK?

struct my_struct* create_my_struct(int param, char *buf)
{
 struct my_struct* md = (struct my_struct*)malloc(sizeof(struct my_struct) + sizeof(int)*param);
 md->size = param;
 md->ptr = malloc(param);
 if (buf)
  memcpy(md->ptr, buf, size);
 return md;
}


なんにせよ、構造体のサイズが不定って段階で create/delete 方式だね。
後でもっとよい実装を思いついたときにも直しやすそうだ。


359:デフォルトの名無しさん
10/04/24 02:59:04
いや、全然ダメだろ
create_unko()の第一引数が冗長だし、リソース開放できなくなってるし
どうでもいいけど、いまどきvoid *の代わりにchar *使わなくても
あと、変更しない変数にはconstを明示的に付けた方が幸せになれる

360:デフォルトの名無しさん
10/04/24 03:00:37
豪快にかぶったけどまあどうでもいいな

361:351
10/04/24 03:04:33
分かりにくかったので、>>354に追加します。

int do_some_process_to_my_struct(struct my_struct* md, int param)
{
 for(int i = 0; i < md->size; i++){
  ((int*)md->ptr)[i] = param+i;
 }
 return param+i;
}

int get_data2(char* buf, int size)
{
 struct my_struct* md = create_my_struct(size);  //←ここでbufを渡せたら
 do_some_process_to_my_struct(md, 12345);
 int ret = memcpy(buf, md->ptr, size);         //←ここでコピーしなくていい
 delete_my_struct(md);
 return ret;
}

362:351
10/04/24 03:12:28
>>358
いいえ。OKではないです。
memcpyするのはあくまでも例ですので、createの中にmemcpyを入れてしまうのは話が違ってしまいます。

知りたいことは、>>351に書いたとおり、関数から構造体を返す場合に
(1)と(2)あるいはその他の方法で良いやり方があるのか、ということです。

363:351
10/04/24 03:19:32
>>361
int do_some_process_to_my_struct(struct my_struct* md, int param)
{
 int i;
 for(i = 0; i < md->size; i++){
  ((char*)md->ptr)[i] = (char)(param+i);
 }
 return param+i;
}

あくまでも例ですが、間違っていたので訂正します。

364:デフォルトの名無しさん
10/04/24 03:23:36
やりたいことがまったく分からなくなってきたので
もう少し簡潔にわかりやすく実例込みで説明頼む

365:デフォルトの名無しさん
10/04/24 04:35:09
マクロでsubstituteする良い方法無い?
#define substitute_ptr(a) ??
#define fn_typedef(a,b) typedef a(*fn##substitute_ptr(a)##substitute_ptr(b))(b);

fn_typedef(ANYSTRUCT*const,int); → typedef ANYSTRUCT*const (*fnANYSTRUCTconstint)(int);

366:デフォルトの名無しさん
10/04/24 06:47:19
printf( "sin(π) = %g \n" ,sin(M_PI) );

sinπが0にならないんだけど?

367:デフォルトの名無しさん
10/04/24 07:04:50
そんくらいの誤差は出るだろ

368:デフォルトの名無しさん
10/04/24 07:47:45
>>351
struct my_struct {
 int size;
 struct {
  char param;  /* malloc からchar型を想定 */
  int data;
 } elem[];
};

こういうふうにペアにしたらダメ?
型の異なる(しかし要素数の等しい)可変長サイズを持つ構造体を取り扱いたいようだが…

369:デフォルトの名無しさん
10/04/24 09:17:20
>351

元々の質問は、一般的にはその2通りのやりかただろう、と答える。
しかし(1)のデメリットが理解できない。
(1)のデメリットは呼び出し元で「入れたいメモリー領域がある場合」、createした構造体をコピーする必要がある。

とくに「入れたいメモリ領域がある場合」という部分が不明。
ポインタがメンバになっているときに、その実体が欲しいってこと?

>354 >361を見てると、あってんだか違うんだか。creat関数の中でメンバを取得しようとしているのかワケワカ。

もしメンバがの実体が欲しいなら、そういう機能を実現した関数を作ればよい。

こんな感じじゃないか。

void get_data(struct my_struct* pMyData, void *pData)
{
 pData = malloc(pMyData->size);
 memmove(pData, pMyData->ptr);
}

370:デフォルトの名無しさん
10/04/24 09:55:27
関数ポインタの配列について教えてください。

void func1( );
void func2( );
void main()
{
int i;
void (*func_ptr[2])( )= { func1, func2};
for(i=0; i<2; ++i)
{
(*func_ptr[i])( ); /* ★★★★ */
}
}
void func1( )
{
printf("func1\n");
}
void func2( )
{
printf("func2\n");
}


上記のプログラムでfunc1とfunc2が実行できたんですが、
★★★★のところを(func_ptr[i])( ); としても、func1とfunc2が実行できました。
関数ポインタの配列に*を付けた場合と付けない場合は何が違うのでしょうか?

371:デフォルトの名無しさん
10/04/24 10:00:40
281 名前:デフォルトの名無しさん[sage] 投稿日:2007/11/08(木) 00:27:05
関数ポインタって代入時の&と実行時の*ってなくても動作変わらないよね?
もともとはどっちが正しいの?

282 名前:デフォルトの名無しさん[sage] 投稿日:2007/11/08(木) 01:06:42
元々必要だったらしいが、gccがなんか理論武装して独自拡張として省略しても良くしたら、
世間に受け入れられたなんて話を聞いたことがある。

372:デフォルトの名無しさん
10/04/24 10:10:25
a[3]と*(a+3)は何が違う
ってきくようなもの
書き方が違うだけでまったく同じ

373:351
10/04/24 10:42:37
>>368
struct my_struct はあくまでも構造体の一例です。
今回の質問ではstruct my_struct の中身を工夫することはあまり重要ではありません。

一般的な話として、関数から構造体を返す場合の、関数プロトタイプの設計に定石があるかどうかを知りたいのです。
こういう時にはこうすれば良いという指針があれば知りたいです。

>>369
>ポインタがメンバになっているときに、その実体が欲しいってこと?

いいえ。今、具体的な構造体あって、その構造体を扱う関数の作り方を知りたいということではありません。

質問の意図は、
構造体を初期化あるいは生成する関数を設計するときの一般論として、
例えば
「ポインタがメンバーになっている構造体の場合は(1)が良くて、そうでない構造体は(2)が良い」(←これは例です。)
というような定石があれば知りたい、ということです。

ですので、get_dataの作り方は質問の対象ではありません。
質問の対象は>>351の(1)(2)の関数プロトタイプについてです。

374:デフォルトの名無しさん
10/04/24 11:43:19
>>351
趣旨が良く分からんのだが、要するに、
構造体の中身を動的にメモリを確保しなくちゃならん時に、
構造体自身も動的に確保したい場合、
一緒に確保した方が良いのか、別々に確保した方が良いのかって話?


375:370
10/04/24 11:43:48
>>371-371
回答ありがとうございます。
*を付けると、func1という関数名になり最終的には、
関数名だけ書いた場合はアドレスになるというルールでアドレスになる。

*を付けないと、func1のアドレスになる

どちらでも同じようにfunc1が実行されるということで合ってますでしょうか?

376:351
10/04/24 11:46:36
>>374
そうですね。
どういう場合には一緒に確保したほうが良くて、どういう場合には別々に確保したほうが良いという指針があれば知りたいです。
他にもっと良いやり方があればそれも知りたいです。

377:デフォルトの名無しさん
10/04/24 12:59:50
>>376
その構造体の隠蔽具合や生命期間との相談かな

FILE ぐらい がちがちに隠蔽する
  関数利用側は基本的にメンバアクセスしない: 操作関数(群) とセットになる
気なのか (この場合は create/delete で完結すべき)

リスト的用途に近く、親struct の生命期間とは生きている必要がある時間が
違う場合は、メンバは alloc せず NULL のまま


378:デフォルトの名無しさん
10/04/24 13:23:31
>>351
あぁ~、やっぱり、趣旨がいまいち良く分からんな…。

>>354のget_data()の使い方を見るとcreate_my_struct()した時に、
領域の確保だけでなく、実際に必要なデータが作成されて、
その内容をget_data()で引っ張るって仕組みって認識したんだが、
ってことは、(1)でのcreate_my_struct()は、
メモリの確保だけでなく、データまで作成するって認識であってる?
で、(2)ではinit_my_struct()でデータだけ作成するってこと?
※ここでのデータ作成は、メモリの動的確保を含む

と言う事であれば、そのinit_my_struct()で作成すべきデータは
それだけで、一つの構造ってことになるから、
それぞれ用のcreateを作るが正しいと思うのだが?

仮にinit_my_struct()をcreate_my_struct2()とすると
create_my_struct()の中でcreate_my_struct2()を呼び出すイメージ。
で、その時々で必要なcreate()を呼ぶ。

379:デフォルトの名無しさん
10/04/24 14:04:10
>>376
俺も概ね>>377と同意見。
他のやり方としては、構造体なら関数の戻り値として
構造体の実体を返す方法もあるよ。
エラーを返しづらかったり、癖の強いやり方だけど。

380:デフォルトの名無しさん
10/04/24 14:34:29
板違いだったらすみません。。。
C言語(WinAPIを含む)でグローバルIPアドレスを無理やり変えることはできますか?

381:デフォルトの名無しさん
10/04/24 14:42:44
通信できなくなるでしょ

382:デフォルトの名無しさん
10/04/24 14:47:21
>>380
C言語(WinAPIを含む)を使って、何の機器のグローバルIPを
どんな意味で変えたいのによるな
何もしても、このスレないことは確か。

383:351
10/04/24 14:59:48
>>377
>その構造体の隠蔽具合や生命期間との相談かな

なるほど。この指標は考える上での参考になりそうです。

ただちょっと初めの質問の意図と違ってきたので、ちょっと考え直します。

384:デフォルトの名無しさん
10/04/24 15:06:31
>>381-382
無理ってことでしょうか?

たとえば掲示板などに書き込むと管理者には
グローバルIPがわかる($_SERVER["REMOTE_ADDR"])と思うのですが、
それをルータ、パソコンをシャットダウンしなくても
ソフトで簡単に変えられたら便利かな?って思ったので・・・

もっと深く突っ込むと
IP斬られてしまったりした場合にすぐに変更できれば
またレスできるぢゃないですかw

それをしたいんです・・・

385:デフォルトの名無しさん
10/04/24 15:09:03
>>384 板違い。

386:デフォルトの名無しさん
10/04/24 15:10:44
>>385
板違いですか?
WinAPIだと思ったので・・・

387:デフォルトの名無しさん
10/04/24 15:11:55
>>384
IP変えるとか、それ以前の問題だな
ネットワークの知識とか、モラルとか、1からやり直せ

388:デフォルトの名無しさん
10/04/24 15:12:27
>>386 URLリンク(pc11.2ch.net)

389:351
10/04/24 15:36:11
標準ライブラリにstrdupがあります。strdupは内部でmallocします。(>>351の(1)に相当)

char *strdup(const char *s);

char* str = strdup("hogehoge"); //←確保するメモリー領域のサイズはstrdupのおまかせ!○
printf("%s\n", str); //処理の例
free(str); //freeが必要×

同等のことを行うmy_strdupを作ることもできます。my_strdupは内部でmallocしません。(>>351の(2)に相当)

void my_strdup(const char* src, char* dst, int size);

char str[100]; //←コピーする文字列より大きなサイズのメモリーが必要×
my_strdup("hogehoge", str, sizeof(str));
printf("%s\n", str); //処理の例
//freeは必要ない!○

(次に続く)

390:351
10/04/24 15:37:17
>>389の続き)

【my_strdupのメリット】
strdupは、内部でmallocをするため、呼び出した後、必ずfreeが必要になります。
一方、my_strdupなら、自動変数を引数に渡せるので、必ずしもfreeは必要ありません。
この点では、my_strdupの方が便利です。これがmy_strdupのメリットです。

【strdupのメリット】
しかし、my_strdupでは、文字列全体をコピーしたい場合、
元の文字列よりも大きなサイズのメモリー領域を渡さなければ、文字列全体をコピーすることが出来ません。
このため、my_srtdupを呼び出す前に、strlenを使うなどして元の文字列のサイズを知る必要があります。
一方、strdupは内部で必要なサイズの領域をmallocするので呼び出す前に元の文字列のサイズを知る必要はありません。
この点では、strdupの方が便利です。これがstrdupのメリットです。

以上は文字列での例でしたが、
構造体や他のデータ領域を扱う関数を考えるときにも
呼び出し元でメモリーを確保して渡すか、あるいは関数の内部でmallocするか、
についてどういう時にどうしたらいいのか、を考えることができるかと思います。

一般的な指針があれば知りたいです。

391:デフォルトの名無しさん
10/04/24 16:12:35
strdup()のデメリットがfree()を必要とすることでは無い
オブジェクトを生成したら破棄するのは当然のことである(create/destroyの対が大切)

my_strdup()のメリットが自動変数を引数に渡せるとかなんとか言っているが
自動変数の領域が足りない場合や書き換えが必要な場合、結局メモリ確保が必要となり自動変数が渡せることはデメリットでしかない

たとえば、標準ライブラリのf*()について考えてみよう
FILEがクラスでfopen()がコンストラクタ、fclose()がデストラクタ、その他のf*()関数がFILEインスタンスに対するメッセージと考えれば、f*()群は低級なオブジェクト指向をしているとか意釈できる

ここで、一つの指針を示そう
あるオブジェクトを生成しメッセージを送り破棄せよ
foo_t *foo;
foo = create_foo();
do_something_foo(foo);
destroy_foo(foo);
呼出元が生成と破棄を対にして行うのが良い

この関係は、strupでもmy_strdupでも同じことになる
char *s = strdup(foo); /* create */
(void)s; /* do something */
free(s); /* destory */

char *t = malloc(bar); /* create */
my_strdup(foo, t, bar); /* do something */
free(t); /* destory */
my_strdup()がソースとデストが逆のmemcpy()みたいで気持ちが悪いと言っておくテスト

392:351
10/04/24 16:38:53
>>391
> strdup()のデメリットがfree()を必要とすることでは無い
> オブジェクトを生成したら破棄するのは当然のことである(create/destroyの対が大切)

確かに当然のことです。当然のことですので、その当然のことを忘れた場合、深刻なバグになるという大きなデメリットがあります。

> my_strdup()のメリットが自動変数を引数に渡せるとかなんとか言っているが
> 自動変数の領域が足りない場合や書き換えが必要な場合、結局メモリ確保が必要となり自動変数が渡せることはデメリットでしかない

自動変数で問題がいない場面では、上記の深刻なバグを避けられるという点で十分メリットがあります。
仰りたいことはわかりますが、一概に決められるものではないと思います。

例えば、>>391の主張では、memcpyはデメリットしか無いことになってしまいますよね?

> 呼出元が生成と破棄を対にして行うのが良い

良いのはわかります。つまり、それがstrdupや、>>351の(1)の場合ですよね。
my_strdupにmallocで確保したメモリー領域を与え、使用後freeするのも良いと思います。

ですが、my_strdupに自動変数を渡してはいけないということにはならないですよね?下記のようなコードは普通に書かれると思います。

void func(const char* str) //strは99文字以下の文字列
{
 char buf[100];
 strncpy(buf, str, sizeof(buf));
 /*strに対する処理*/
 printf("%s\n", str);
}

これは、若干恣意的な例ですが、これに限らず、自動変数の構造体や配列へのポインターを関数に渡すことは一般的に行われることですよね。

393:351
10/04/24 16:43:53
>>392の訂正です。すいません。

void func(const char* str) //strは99文字以下の文字列
{
 char buf[100];
 strncpy(buf, str, sizeof(buf));
 /*bufに対する処理*/
 printf("%s\n", buf);
}


394:デフォルトの名無しさん
10/04/24 17:20:21
>392
バグ(メモリリーク)になるから自動変数使うとかどれだけ舐めてるんだよ
C言語はプログラマ任せだからそんなこと言うようになったら、もうC言語に触れない方が幸せになれるよ

別にmemcpy()がデメリットしかないダメダメ関数とは言っていない
一般化したいと言っているのに自動変数マンセーとか言っているからだよ
自動変数(オブジェクト)に対してmempcy()(メッセージ)を送っているが、領域不足やコピーが必要になったときに結局メモリ(新しいオブジェクト)が必要になるのなら最初からメモリ使っておけばいいだろ
つまり、一般的にあるオブジェクトに対するメッセージの引数に自動変数が渡せるからって嬉しいことは無いだろと
memcpy()は抽象し過ぎているから混乱しているんだろう

別に、my_strdup()に自動変数を渡してはいけないとは言っていない
少なくとも自動変数が渡せることがメリットにはならないし、一般的に考えれば自動変数を使うことはデメリットになると言及しただけのこと

確かに、自動変数で領域や生存期間が足りるのであれば自動変数でも構わない
しかし、一般化してオブジェクトがN個必要なときに困ったことになる
ある場面ではi個必要で、自動変数をi個用意しなければならない、またある場面ではj個必要で、自動変数をj個用意しなければならない
じゃあ、i <= jだから、j個用意しとけばいいやとするのか、iが遥かにjより小さい場合無駄が多いからすべきでは無い
そんなことしないで、必要な時に必要なだけ用意してやれば済むこと


一般化したいのか具体化したいのかどちらかにしてもらえないだろうか

395:351
10/04/24 17:40:07
>>394
構造体や配列を返す関数を設計する場合の一般的な指針を求めています。

>C言語はプログラマ任せだからそんなこと言うようになったら、もうC言語に触れない方が幸せになれるよ

C言語はプログラマ任せだからこそ、プログラマーが、その時々に適切に、自動変数を渡すか、mallocで確保したメモリーを渡すかを選べるようにしておく方が幸せでしょう。
ですので、自動変数をマンセーしているわけではありませんが、自動変数を一切渡せないよりは、渡せた方がメリットがあると考えます。

つまり、自動変数を一切渡せなければ、自動変数を使いたいプログラマーには使えませんが
自動変数を一切渡せれば、自動変数を使いたいプログラマーにも、使いたくないプログラマーにも使えるからです。
これは十分メリットです。

ともかく、自動変数を渡せるかどうかは、今回の質問の本質ではなく、
構造体や配列を返す関数を設計する場合の一般的な指針として、
(1)関数内部でmallocするのと、(2)呼び出し側で確保したメモリー領域を受け取るのと、(3)それ以外の方法(があれば)と、で
どういう時にどうするのが良いのかという指針があれば知りたいと思っています。

396:デフォルトの名無しさん
10/04/24 17:56:48
>どういう時にどうするのが良いのかという指針があれば知りたいと思っています。

ないよ。問題が無い限り好きにしてよしヽ( ´ー`)ノ

397:351
10/04/24 18:05:31
「好きにしてよい」というのは、特に基準がないのでその日の気分でどちらかに決めるということですよね。
そういう方針の方もいるということはわかりました。ありがとうございます。

それでは引き続き、>>389-390について何か方針をお持ちの方がいましたら、ぜひ教えてください。お願いします。

398:デフォルトの名無しさん
10/04/24 18:24:44
WindowsのAPIは、my_strdup()みたいに格納領域のアドレスとサイズを
渡すインタフェースが多いね
で、Windows系のプログラマはそういう関数をつくることが多いね
無難だけど美しくないよね
パラメタは少ない方がいい

399:デフォルトの名無しさん
10/04/24 18:38:23
>>389
とりあえず、strdupは例として適当じゃないわな。目的が違うから。
単に(最大の)長さが分かっている文字列のコピーは
strcpyなりstrncpyなりを使う。

一般論で言って、必然性がない場合、mallocはしない。
する場合は、旧来では
・確保すべきサイズがかわる
・スコープを越える必要がある

他のケースはプログラマの腕次第で
コードをシンプルにするために使う。
・引数を減らす
・必要な変数を減らす
・インターフェイスの一般化
などなど。

メモリ管理に自信がないならやめとき。

ただイマドキ、そこに自信が持てないなら
Cなんて使わない。
逆に言えば、その程度は必須なわけで、
だから「好きにすれば良い」って意見が出てくる。

400:デフォルトの名無しさん
10/04/24 19:25:00
>351

生成と解放を対にしろってのは、基本方針としてもよいと思う。
よって、strdupのような関数は、できれば使いたくない派。
strdupは生成と解放の数が合わなくなる。

>392
>> 呼出元が生成と破棄を対にして行うのが良い

>良いのはわかります。つまり、それがstrdupや、>>351の(1)の場合ですよね。

これ逆だよね。strdupを使うとmallocが見えないのにfreeしなくちゃならない。

strdupは標準関数だからましだけど、func0, func2, func4が返すポインタは
freeしてね、とかだとやってられない。


やけにstrdupが「サイズを気にしなくてよい」ことがお気に入りのようだが、あくまでも実引数がCstringである場合だけ。
これは自動変数か、ヒープ領域か、静的変数かには無関係。

str系関数は、終端文字がある前提という制限がある。

呼び出し側が領域を用意する場合は、当然呼び出し側でサイズがわかっているはずなので、
そのときに無駄に領域を用意しなければよいだけでしょ。


401:デフォルトの名無しさん
10/04/24 19:32:16
急に流れが加速してて吹いた。

402:351
10/04/24 19:32:36
>>399
> 一般論で言って、必然性がない場合、mallocはしない。
> する場合は、旧来では
> ・確保すべきサイズがかわる
> ・スコープを越える必要がある

これには同意です。
個人的には自動変数で済む場合はmallocは使わないようにしています。

> コードをシンプルにするために使う。
> ・引数を減らす
> ・必要な変数を減らす
> ・インターフェイスの一般化

これは、シンプルになるのであれば、シンプルにしたほうがいいということですね。
つまり、>>351の(1)が可能であれば、常に(1)にしろということですね。
方針の一つとして参考にさせていただきます。

403:デフォルトの名無しさん
10/04/24 19:34:03
・サイズが巨大な場合
が抜けてるな

404:351
10/04/24 19:45:44
>>400
>生成と解放を対にしろってのは、基本方針としてもよいと思う。
>よって、strdupのような関数は、できれば使いたくない派。

個人的にはstrdupは使いませんが、
strdupもstrdup-freeで生成と解放の対になっているので問題ないと思います。
(n対1の対応なので若干違和感はありますが。)

>これ逆だよね。strdupを使うとmallocが見えないのにfreeしなくちゃならない。

いいえ、関数の中でmallocを行うという点で、strdupと>>351の(1)は同じです。
create_my_struct()に対するdelete_my_struct()は、strdup()に対するfree()です。

405:デフォルトの名無しさん
10/04/24 19:52:13
strdupって名前が気に入らないんじゃないの
"alloc" を含んでないから
俺は別にどうでもいいと思うけど

406:デフォルトの名無しさん
10/04/24 20:00:01
関数の実体が書いてないから、何とも言えないね

407:デフォルトの名無しさん
10/04/24 21:35:25
>>398
上位互換を維持しつつ ver 違いを吸収する苦肉の策な面もあるね

APIを実装する際「渡されたサイズからどのver なのか類推・分岐できる」

408:デフォルトの名無しさん
10/04/24 21:57:07
GDI+を使うためにはどうすればいいですか?
VC2008です。

409:デフォルトの名無しさん
10/04/24 21:57:40
上位互換を持するということは、元の関数から引数は変化がないということだろ。
元の関数から変化が変化がないということは、元の関数もアドレスとサイズを持っていたということであって
つまり元々あるのだから苦肉の策では無いんじゃないの。

410:デフォルトの名無しさん
10/04/24 22:07:16
>>408
#include <gdiplus.h>
#pragma comment(lib, "gdiplus")

411:デフォルトの名無しさん
10/04/24 22:10:20
>>410
VC++の他に特に何もいらないということですね。
質問にこたえていただきありがとうございます。

412:デフォルトの名無しさん
10/04/24 22:11:41
VC++EE使ってるならPlatformSDKがいるんじゃ

413:デフォルトの名無しさん
10/04/24 22:14:01
例がたまたまかもしれないけど、my_strdupを使うくらいならstrncpyを使うよね。

話を戻すと、allocとfreeは同じレイヤーにあるのが分かりやすいと思うよ。

414:351
10/04/24 22:26:58
>>413
> 話を戻すと、allocとfreeは同じレイヤーにあるのが分かりやすいと思うよ。

それはそのとおりだと思います。
>>351の(1)(2)ともにその方針に基づいています。
(1)の場合は自前でalloc-freeを行い、(2)の場合は前処理・後処理として必要な場合のみalloc-freeを行います。

今回の質問の趣旨はそこではなく、
構造体や配列を返す関数を設計する場合の一般的な指針を知りたいのです。

415:デフォルトの名無しさん
10/04/24 22:42:53
>>351
俺は、is-aと考えた方が自然なのかhas-aと考えた方が自然なのかで分ける。
分かるとは思うが(1)はis-aの場合で、(2)はhas-aの場合。
あと、自動変数を使用するか、アロケートするかは、
プログラマが使いたいか使いたくないかで考えるのではなく、使用用途で考えるべき。

416:デフォルトの名無しさん
10/04/24 22:45:55
> (1)のデメリットは呼び出し元で入れたいメモリー領域がある場合、createした構造体をコピーする必要がある。
入れたいメモリ領域がある場合はinitのパラメータにもたせれば良いのでは?

> (2)のデメリットは呼び出し元でinitを呼ぶ前に構造体の大きさを知っていなければいけない。
my_struct *p = (my_struct *)malloc(sizeof(my_struct));
ではだめだということ?

常に呼ばなければならないreleaseを作成するのであれば、常にinitの中でallocすればいいと思う。
そうでないのなら、構造体本体は利用者がalloc-freeすればいいと思う。というか、そうしてる。

417:351
10/04/24 23:00:41
>>415
なるほど。その指針は明快ですね。納得です。
ありがとうございます。

>>416
>> (1)のデメリットは呼び出し元で入れたいメモリー領域がある場合、createした構造体をコピーする必要がある。
>入れたいメモリ領域がある場合はinitのパラメータにもたせれば良いのでは?

つまり、常に>>351の(2)にするのが良いということでしょうか?

>> (2)のデメリットは呼び出し元でinitを呼ぶ前に構造体の大きさを知っていなければいけない。
>my_struct *p = (my_struct *)malloc(sizeof(my_struct));
>ではだめだということ?

はい、ダメです。
struct my_structは可変長配列のメンバーdataを持っているのでそのサイズ分多めにメモリーを確保しなくてはいけません。

418:デフォルトの名無しさん
10/04/24 23:19:22
入れたいメモリ領域を渡したいことについて
(2)のinitのパラメータに持たせてもいいし、(1)のcreateのパラメータに持たせてもいい。

可変部のサイズを常にパラメータで渡すのであれば、呼び元でそのサイズを確保することは
十分可能なんじゃないの?

419:デフォルトの名無しさん
10/04/24 23:28:12
>>409
いや パラメータが一括で纏まった構造体 ってパターンがほとんどさね
ListView とか IEのVER違いで、パラメータ構造体のサイズが違う
だが API(要素の追加とか)のインターフェースは不変
(さらに、APIの実装体は外部リンケージなDLL内)
こういうこと

この例でない話だったらスマン

420:351
10/04/24 23:42:33
>>418
入れたいメモリ領域を渡すのが(2)で、入れたいメモリ領域を渡さず関数内部でメモリ領域を確保するのが(1)です。これが定義です。
ですので、入れたいメモリ領域を渡すのであれば、(2)になります。

また、(1)の場合は、可変部の情報を含めサイズ情報を渡しません。
ですので、(1)の場合、呼び出し元は可変部の情報を含めサイズ情報を呼び出す前に知る必要はありませんし、
前述のとおり関数内部でメモリー領域を確保するので、そのサイズを知ることが出来なくても問題ありません。

421:デフォルトの名無しさん
10/04/24 23:58:42
>>420
入れたいメモリ領域云々を別で考えることはできないの?
そうなればそれは一般的に構造体を扱う時の指針とかそういうのとは別で、特殊化された話になってこないか?

422:351
10/04/25 00:14:29
>>421
> 入れたいメモリ領域云々を別で考えることはできないの?

これはどう言うことでしょうか?
少なくともどこか(関数内あるいは関数外)で、malloc(sizeof(struct my_struct)+data_size)のように構造体のメモリーを確保しなければならないと考えていました。

もしこれを別で考える方法があるならば、ぜひご教示ください。

423:デフォルトの名無しさん
10/04/25 00:33:19
入れたいメモリ領域ってptrじゃないの?
サイズを可変にするためのものとは別だよね。

このptrを同じ関数で確保すべきか、外から渡せるようにするかという話が混ざっているように見える。

424:351
10/04/25 00:41:35
>>423
>入れたいメモリ領域ってptrじゃないの?

入れたいメモリ領域とは、構造体そのものを入れたい領域のことです。

425:400
10/04/25 00:42:10
>351 >420

あなたの言う1)と2)の違いを、把握できていなかったから、議論がぐるぐる回っていたぞ。

議論の焦点は
>入れたいメモリ領域を渡すのが(2)で、入れたいメモリ領域を渡さず関数内部でメモリ領域を確保するのが(1)です。これが定義です。
ということだね。

そうでであるならば
>(1)の場合は、可変部の情報を含めサイズ情報を渡しません。
これは無理。

1)の実現例としてstrdupを挙げているのなら、str系は終端文字列付きという制限を与えることで、
間接的にサイズ情報を与えている。

>404
>いいえ、関数の中でmallocを行うという点で、strdupと>>351の(1)は同じです。
私には同じには見えないな。
malloc-free, new-delete, new[]-delete, create_my_struct-delete_my_struct
は対に見える。

だけど関数内部でmallocするhogeがあるとしてhoge-freeは対には見えない。
そういうことに注意してコーディングしたくない。

だからstrdup使うくらいなら、mallocしてstrcpyして、freeする。

426:351
10/04/25 00:56:57
>>425
> >(1)の場合は、可変部の情報を含めサイズ情報を渡しません。
> これは無理。

いいえ。無理ではありません。
例えば、関数内でrecv()を使ってネットワークからデータを受信する場合など、処理を完了して初めてデータのサイズが確定することがあります。
そのような場合、関数を呼び出す前にはそのサイズは分かりませんが、関数内ではreallocするなりして適切なサイズのメモリーを確保することができます。
したがって、可能です。

>私には同じには見えないな。

これは関数名が適切ではないとうことでしょうか?
そうであれば特に異論はありません。人の感覚なのでそう見えない人がいることは仕方が無いと思います。
そういう点では、私も、new-deleteという組み合わせが名称としてあまり適切でないと思っています。

私が同じだといったのは、機能としての対応からです。

427:デフォルトの名無しさん
10/04/25 01:52:31
>>426
> 例えば、関数内でrecv()を使ってネットワークからデータを受信する場合など、
> 処理を完了して初めてデータのサイズが確定することがあります。
>そのような場合、関数を呼び出す前にはそのサイズは分かりませんが、
>関数内ではreallocするなりして適切なサイズのメモリーを確保することができます。

なぜ recv() がそういう造りになっていないのか? を想像してくれ
上記の構造だと、生成/消滅の入れ子構造が維持し難いんだよね 

428:351
10/04/25 01:59:41
>>427
> なぜ recv() がそういう造りになっていないのか? を想像してくれ

何のためにその想像をする必要があるのでしょうか?
目的がよくわかりません。

429:デフォルトの名無しさん
10/04/25 03:25:24
>>424
ならぬるぽのときだけ確保するようにしたらいいんでないかな。

430:デフォルトの名無しさん
10/04/25 03:27:29
>>425
うーん、strdup-freeも対に見えないよ
その論調ならstrdupの存在を否定していいと思うんだ。そしてそれはアリだと俺は思う。

431:デフォルトの名無しさん
10/04/25 03:33:04
って最後の行読んでなかった。まったくもってそのとおりであって、なんていうかごめん。

ちなみにnew[]-deleteはnew[]-delete[]の間違いだよな?

>>426
> 人の感覚なのでそう見えない人がいることは仕方が無いと思います。
なんか多分読み違えているけれど、
create_my_structのような関数を見た場合、同ライブラリにdelete_my_structのような関数があれば
プログラマは注意を払うが、なければ特に何もしなくて良い(freeを使う必要がない)と思ってしまうクセがある。
そういう意味で、hoge-freeが対に見えないという話だよ

432:>425
10/04/25 08:44:44
>431

>ちなみにnew[]-deleteはnew[]-delete[]の間違いだよな?

すみません。タイプミス。注意したつもりだったのに、日頃C++使わない物で、ご容赦ください。

>426
他の人とは、同じ感覚みたいだけど、strdup-freeはリソースの確保と解放のレベルがあっていない、
イヤなコーディングスタイルだってこと。mallocしているレベルが、一段低いから。
名前の問題ではない。
ただ、標準関数という意味でギリギリの許容範囲。
コーディングスタイルを操作できる立場なら、ANSIに含まれないから禁止としたいくらい。
拒否する。

もちろんそういう構造が取れない場合は、あり得る。
だけど「一般的には」リソースの確保と解放の対は、そろっている方がよい。


433:デフォルトの名無しさん
10/04/25 09:22:07
>>432
横からだけど、レベル合わせるのって必要か?
どちらかと言うと、アロケートとリリースが組み合わせになってないことの方が問題じゃないか?
strdupに対して、strdup_free()があれば良いだけで、
使う方は、その中身の実装は問わないってのが正解な気がするが…?
要するに、あるオブジェクトに対してのnewがあるなら、
そのオブジェクトに対するdeleteを用意して、それを使えってだけで、
組み合わせを間違えなければ、内部がどうなってようが、問題にならないと思うが…

434:デフォルトの名無しさん
10/04/25 09:41:31
同じく横からだけど
デストラクタが無い影響はスコープだけじゃなく構造体・共用体の中にまで影響する訳で
入れ物の階層毎に都度専用alloc/freeを用意するのが注意深いcデータ取り扱い方だとおもうよ

435:デフォルトの名無しさん
10/04/25 10:05:18
メモリを確保して返す関数は作るなって話か?
確保するメモリのサイズを事前に取得できない場合はどうすんのって話だな

436:デフォルトの名無しさん
10/04/25 10:14:03
専用reallocを用意するだけじゃないの?

437:デフォルトの名無しさん
10/04/25 10:23:15
とりあえず malloc して、そのポインタのアドレスを渡して、
関数内で realloc してもらうとか?

438:デフォルトの名無しさん
10/04/25 10:30:07
>>437
分けも分からずmalloc()する位なら、NULL使ってrealloc()の方がまし

439:デフォルトの名無しさん
10/04/25 10:35:23
それだと malloc/free の対応がとれないって主張なんじゃないの

440:デフォルトの名無しさん
10/04/25 10:43:30
>>439
必要なのはC++で言うnewとdeleteに対応するものであって
mallocとfreeではないと思うのだが?

441:432
10/04/25 10:45:57
>433

>strdupに対して、strdup_free()があれば良いだけで、

それがレベルを合わせるってこと。
strdupの中でmallocしていれば、strdup_freeで責任もってそれを解放する方が、コード上で
リソースバランスの確認ができる。

>組み合わせを間違えなければ、内部がどうなってようが、問題にならないと思うが…
内部を気にしたくないから、リソース管理の責任レベルを合わせたいってこと。

>435
>確保するメモリのサイズを事前に取得できない場合はどうすんのって話だな
必ずしも、同じレベルでそろえられないかもしれない。でも、大抵は設計が行けてないだけ。

少し話を戻して>432で
「名前の問題ではない」と書いたけど、リソース管理レベルの話題であって、名前の話ではないといういみであり、
人間がコードを書いている以上、リソース管理レベルは識別子で認識している。
従って、リソース管理レベルを意識していれば、名前もそうなるはず。

コード上で名前のバランスが取れていない場合、設計を疑った方がよい。



442:441
10/04/25 11:00:58
>426

>> >(1)の場合は、可変部の情報を含めサイズ情報を渡しません。
>> これは無理。
>いいえ。無理ではありません。
>例えば、関数内でrecv()を使ってネットワークからデータを受信する場合など、処理を完了して初めてデータのサイズが確定することがあります。

OK.あなたと私では、視点のレベルが違っていた。
私の視点は事前にサイズがわからない場合も、とりあえずバッファを用意しておいて、
読んでみないことには知りようがない、という意味だったのです。recvそのものの
レイヤーです。読んでみたあとはサイズがわかる、というのはそうですね。


議論はあくまでも一般論です。個別では理想的な実装ができないかもしれません。

余談ですが、メッセージループの処理ならば一般的には、下記のように書くと思います。
擬似コードです。

for (;;) {
 recvMsg(pMsg);
 /* メッセージに応じた処理 */
 freeMsg(pMsg);
}

これはメッセージを受けるところと、最後に解放するところでリソース管理レベルを
そろえています。

443:デフォルトの名無しさん
10/04/25 11:07:19
要するにコンストラクタとデストラクタを用意するみたいな感じにすべき、ということね?
まあその主張は分からんでも無い

444:デフォルトの名無しさん
10/04/25 11:10:13
>>441
>>strdupに対して、strdup_free()があれば良いだけで、
>それがレベルを合わせるってこと。
何か意図が違う気がする。
strdup()内でmalloc()を呼んでようが、さらに、strdup()で別の関数を呼んで
その中で、malloc()を呼んでようが、俺は気にしないって話だが合ってる?
strdup_free()に関しても、冗長になると分かってても実装して欲しと思うが、
最悪(本当に最悪だが)はdefineの定義するだけでも構わないと思ってるけど同じ?

445:351
10/04/25 12:24:26
>>442
>議論はあくまでも一般論です。個別では理想的な実装ができないかもしれません。

はい。そのとおりです。
ですが、その下の擬似コードは>>351の質問の意図を表していません。

>>351の質問の意図は、
recvMsg(), freeMsg()を使う関数を作るような場合を含めて、
一般的に
・関数から構造体を返す必要がある場合、何か基準や定石があるのかを知りたい。
・こういう時にはこうすれば良いという指針があれば知りたい。
ということです。

recv()とrecvMsg()-freeMsg()のどちらが一般的かという議論は今回の質問の中ではしていません。

446:デフォルトの名無しさん
10/04/25 12:29:35
>>445
構造体自体を返すだけなら free() はいらない。
でも >>351 のお題にあがっている構造体は、メンバに malloc() で得たポインタがはいっているので、
当然 そのポインタを free() する必要がある。
一般化というが、上記のことだけ注意すれば OK なのでは。

447:デフォルトの名無しさん
10/04/25 12:30:02
>>351俺なら(1)だな。

さらに、(オーバーロードできるなら、C++なら同名で)
void delete_my_struct(struct my_struct **md) {
 delete_my_struct(*md);
 *md = 0;
}
とすらする。

448:デフォルトの名無しさん
10/04/25 12:32:34
>>447
Cでオーバーロードできる環境なんてあるのか?

449:351
10/04/25 12:36:38
>>446
つまり、構造体内部の後処理だけを関数で行えということなので、常に>>351の(2)が良いということですね。

>>447
どういう場合、>>351の(1)が良いですか?
基準があれば教えてください。

それとも、常に>>351の(1)が良いでしょうか?

450:デフォルトの名無しさん
10/04/25 12:51:51
>>448
いっけね。Cスレだった。C/C++かと思ってた。

>>449
基準も何も、(2)は俺にとって煩雑。
呼び出し元でmallocなりして、init_my_struct呼んで、
要らなくなったらrelease_my_struct呼んで、free呼ぶ。
呼び出し回数が多い。呼び忘れるのも怖い。

(1)ならcreate_my_structで生成と初期化を同時に行い、
delete_my_structで後片付けと削除を同時に行う。
呼び出し回数が少ない。余計な気を使わなくて良い。
create - deleteの対を分かって使えば良いだけ。

C++にしたってコンストラクタ以外に、
new後にinit()呼び出しを要する設計もあるが、
同じ理由で俺はそういうの嫌い。

メソッド間、関数間に呼び出し順の依存関係があると使いにくい。

451:デフォルトの名無しさん
10/04/25 13:33:21
>>351 は構ってちゃんだから、マジレス禁止ね(^o^)ノ

452:デフォルトの名無しさん
10/04/25 13:54:52
>>351は常に(1)でいいよ。
ただし構造体のメンバにアクセスできないようにカプセル化したほうがいい。
ヘッダに

  struct my_struct* create_my_struct(int param);
  void delete_my_struct(struct my_struct* md);
  その他my_structを操作する関数のプロトタイプ宣言

を書いて、ソースのほうに

  struct my_struct {
   int size;
   void *ptr;
   int data[];
  };
  関数の定義

を書く。

453:351
10/04/25 18:27:17
>>450
> 基準も何も、(2)は俺にとって煩雑。
>>452
> >>351は常に(1)でいいよ。

ありがとうございます。基本は(1)ということですね。

では、呼び出し元で構造体を格納したい場所が決まっている場合はどうすればいいと思われますか。

>>351の(1)の場合は、
呼び出し元で構造体のcretateを実行し、呼び出し元でその結果を構造体を格納したい場所にコピーしなければなりません。

>>351の(2)の場合は、
呼び出し元で構造体のinitに格納したい場所を指定して実行すれば、結果として格納したい場所に構造体が格納されるので、呼び出し元では改めてコピーする必要はありません。

この点で、やはり(2)は捨て切れません。
上位でどう使われるかわからない関数を設計する場合は、やはり(1)(2)の両方を用意したほうがいいでしょうか。

(1)(2)以外にうまい方法があれば知りたいところです。

454:デフォルトの名無しさん
10/04/25 18:51:27
>>453
自分で答え出してるじゃないか。まだ何か困ってるの?

455:351
10/04/25 18:53:31
>>454
はい。
>>453の一番最後の行に書きました。

456:デフォルトの名無しさん
10/04/25 19:30:23
>>455
へぇ。そこ読んでも俺には何に困ってるのかわかんないや。

457:デフォルトの名無しさん
10/04/25 19:34:52
>>351
何のために格納したい場所ってのが必要なのかわからんが、変な書き方するよりは
おとなしくコピーしたほうがいいかもね。

458:351
10/04/25 19:43:23
>>457
格納したい場所が決まっている状況というのは、
例えば、下記のようなコールバックハンドラーを実装する場合に、引数に格納するメモリー領域を渡されるような場合です。

int (*some_callback_handler)(char* buf, int buf_size);

パフォーマンスがそれほど要求されない場面では確かにコピーすれば解決なのですが、
そうではない場合もあるので、コピーの回数は減らせられるようにもしたいのです。

459:デフォルトの名無しさん
10/04/25 19:56:46
おかしいな、引数がヌルポインタかどうかで判断すればいいよっていうのはどうしちゃったんだろ。
reallocみたいな感じといえばいいかな

460:デフォルトの名無しさん
10/04/25 21:13:28
>>458
get_my_struct関数を作ってポインタを返して、そのポインタを使えばいいのでは。

461:351
10/04/25 21:24:14
>>460
構造体を格納したいポインタを知っているのは呼び出し側なので
get_my_struct関数を作っても仕方ないですよね?

462:デフォルトの名無しさん
10/04/25 23:54:00
まだやってんのか

こういうどうでもいい質問はOKウェブみたいな初心者向けQ&Aサイトでやればいいのに

463:デフォルトの名無しさん
10/04/26 00:03:24
>>462
それがこのスレさ

464:デフォルトの名無しさん
10/04/26 11:01:21
いや寧ろ、ここは>351みたいに捻くれた初級者向きじゃない。
いっそ小心者スレ辺りでやってほしい。

465:デフォルトの名無しさん
10/04/26 13:02:05
>>464
お前が童貞専用自慰スレに行けばいい

466:デフォルトの名無しさん
10/04/26 22:05:24
フローチャート記号の「準備」ってどうやって使うものなの?
変数の宣言というのがこういうので、この時に使う?↓
int nurupo;
これは「処理」でいいよね?↓
int nurupo = 1

467:デフォルトの名無しさん
10/04/26 22:14:54
int nurupo = 1
が準備だな

処理に備えて初期化という準備をしているわけだし
変数宣言はフローチャートの中では書かないことが多い

468:デフォルトの名無しさん
10/04/26 22:52:29
会社で初期化と同時に代入書いたら
「こんな書き方見たことない、直せ!」と言われた。

469:デフォルトの名無しさん
10/04/26 23:02:07
初期化と同時に代入ってどうやるんだ

470:デフォルトの名無しさん
10/04/26 23:02:55
int i;
int j = i = 0;

こういうやつか
まあキモいな

471:デフォルトの名無しさん
10/04/26 23:03:11
>>469
語弊があって申し訳ないが、>>467みたいなやつ。

472:デフォルトの名無しさん
10/04/26 23:06:20
「初期化」と「代入」を勉強し直させるべきだな
つーか見たことない、って

473:デフォルトの名無しさん
10/04/26 23:08:35
宣言と同時に代入ってことか?

474:デフォルトの名無しさん
10/04/26 23:10:00
>>466
ソース読めば瞬間わかることを書いてはいけない
よく読まなければわからないことをアシストしてこそ意味がある

475:デフォルトの名無しさん
10/04/26 23:11:39
>>473
それを初期化と言う
まあ、初期化は代入ではないがな

476:デフォルトの名無しさん
10/04/26 23:26:20
初期化は代入じゃない?
int main(void) {int x = 5; return 0; }
なんかだと代入じゃない?

477:デフォルトの名無しさん
10/04/26 23:34:34
いいえ、初期化です

478:デフォルトの名無しさん
10/04/26 23:41:51
466だけど、アホ言ったみたいでほんとごめん。
もう少しグーグル先生で探してくる。プログラムって難しそうね。。
>>474
そういうものなのね。
じゃあ殆どつかわねーよ!という記号もあるとか?

479:デフォルトの名無しさん
10/04/26 23:46:14
auto 変数に初期化なんかあるのか?全部代入じゃないのか?
それとも俺の頭が古いのか?

480:デフォルトの名無しさん
10/04/26 23:58:19
>>479
古いんじゃなくて、最初からちゃんとした文法を覚えていないだけ。

481:デフォルトの名無しさん
10/04/27 00:01:05
>>480
static な変数に対する初期化は理解できるが、auto な変数に初期化という動作はあるのか

main() {
int x; /* 宣言 */
x = 1; /* 代入 */
}

をひとつにまとめものが
main()

482:デフォルトの名無しさん
10/04/27 00:01:46
int main() {
int x = 1; /* 宣言&初期化 */
}
と思っていたのだが。

483:デフォルトの名無しさん
10/04/27 00:03:31
ごめんなさい。やりなおし。
main()
{
int x; /* 宣言 */
x = 1 /* 代入 */
}
をひとつにまとめたものが
main()
{
int x = 1 /* 宣言+代入 */
}
だと思っていたのだが、規格はこれを初期化と呼んでいるのか?

484:デフォルトの名無しさん
10/04/27 00:11:39
>483

それは、初期化子付きの宣言。あくまでも宣言で、宣言+代入ではない。
式と宣言では文法が区別されている。

int a[] = {1, 2, 3,};
と書けるが
int a[10];
a[] = {1, 2, 3,};
とは書けないのは別物だから。

485:デフォルトの名無しさん
10/04/27 00:16:06
>>483
JIS X3010 6.7.8 初期化

486:デフォルトの名無しさん
10/04/27 01:11:59
>>481
途中で送信したとは思ったがシュール過ぎて笑った。

487:デフォルトの名無しさん
10/04/27 11:47:43
制御系プログラミングの初歩として、C言語(++ではない)のビット演算を勉強しています。
unsigned char型の変数を、二進数でバラして8個の0/1フラグとして使うための一番効率のよいやり方って何ですか?
一般的に使われるロジックとしては以下のメソッドのような感じでOKですか?

//引数srcのnビット目を0か1かで取り出す
unsigned char getNbit(unsigned char src,unsigned char n)
{
//srcと2のn乗(nビット目だけ1の値)と論理乗算して、0になったら0を返す。そうでなければ1。
if( src & (1<<n) == 0 )
{
return 0;
}
else
{
return 1;
}
}

//引数srcのnビット目に指定の値param(0/1)をセットした値を返す
unsigned char setNbit(unsigned char src,unsigned char n,unsigned char param)
{
//0をセットする場合、srcと2のn乗の値を反転した値(255-1<<n)とを、論理乗算する
if(param == 0)
{
return src & (255-1<<n);
}
//1をセットする場合、srcと2のn乗(1<<n)の値とを、論理加算する
else
{
return src | (1<<n);
}
}

488:デフォルトの名無しさん
10/04/27 11:54:37
ビットフィールドじゃあかんの?生成されるコードは汚いけど

489:デフォルトの名無しさん
10/04/27 11:58:10
二つ目はon/offで関数わけようぜ

490:デフォルトの名無しさん
10/04/27 12:00:41
IO操作するならビットフィールド使って、関数で隠蔽する

491:デフォルトの名無しさん
10/04/27 12:15:09
(255 - 1 << n) じゃなくて ~(1 << n)ってするのがビット演算らしい

492:デフォルトの名無しさん
10/04/27 12:34:18
__inline unsigned char getNbit(unsigned char src, unsigned char n) {
return src & (1 << n);
}

__inline unsigned char setNbit(unsigned char src, unsigned char n, unsigned char param) {
return src & ~(1 << n) | (!!param << n);
}

493:デフォルトの名無しさん
10/04/27 12:39:45
return (src >> n) & 1


494:487
10/04/27 13:33:20
皆さん、ありがとうございます。

>>490
まさにIO制御の学習です。
基盤にランプが8個乗っていて、指定のIOポート1つ(1バイト)に値をセットすることで点灯/消灯を制御するといった課題です。
ビットフィールドというのを調べてみます。

>>492
前者は、指定したビットが0のときは0が返るけれど、1のときは1<<nが返りますね。
それでも、このメソッドを使う際に、「0かそうでないか」という運用をすれば良いということですか?
JavaのbooleanやC#のbool型に慣れているゆえ、0か1かの戻り値にこだわらないといけないと思っていましたが、
Cの常識だとそうでもないという認識で良いですか?

後者は、「src & ~(1 << n) | (!!param << n);」の記述の意味を詳しく教えていただけると助かります。
「src & ~(1 << n)」の部分までは、「とりあえず指定ビットを0にする」というのは分かりますが、
その後、 !!とはどういう意味の記述なのでしょうか。

こういう短く基本的な処理を書くにはinlineにしたほうが高速なのですね。とても参考になります。

495:デフォルトの名無しさん
10/04/27 13:38:56
ビットフィールドの実装依存の部分からいってその用途には使えないんじゃないの?
パディングとか順番入れ替わるとかで

496:デフォルトの名無しさん
10/04/27 13:46:15
>>494
>>492の get の方は指摘の通りで、0, 1 に固定するなら(した方がいいだろうけど)、
return !!(src & (1 << n));
としてもいいが、それなら >>493 の方がいいね。

!! は ! を2回やってるだけ。 0なら0、0以外なら1にしたいときにやる常套手段。

497:デフォルトの名無しさん
10/04/27 14:15:09
>>487の判定文、演算子の優先順位をよく調べとけ


498:デフォルトの名無しさん
10/04/27 14:28:54
>>494
JavaでもC#でも0が偽というところは変わらんよ。
if (3)とかかけるでしょ

499:デフォルトの名無しさん
10/04/27 15:34:56
>>498

500:デフォルトの名無しさん
10/04/27 15:42:12
JARO

501:デフォルトの名無しさん
10/04/27 18:54:10
!!はキモいんだよなあ
好みの問題だろうけど
ちゃんと最適化されるかどうかは気になる

502:デフォルトの名無しさん
10/04/27 19:14:22
!!がいやなら!=0はどうよ?

503:デフォルトの名無しさん
10/04/27 19:20:04
>>485
なるほど、「静的記憶域区間」のみならず「自動記憶域区間」の場合であっても、初期化という言葉が適用されるのですね。
インプリメント上では単なる代入にすぎないものであっても。



504:デフォルトの名無しさん
10/04/27 19:53:57
C++で挫折してCに流れ着いてCの入門書読み終えたんですが、中級者になるために試したらためになる演習課題とかありませんか
たぶんメモ帳とか作る場合GUIとか使わないとならないんですよね?できたらヒント付きで教えてくれませんか?


505:デフォルトの名無しさん
10/04/27 19:54:16
>>502
俺は基本そうしてる
if文に直接書く時はそれすら書かないけど

506:デフォルトの名無しさん
10/04/27 19:55:02
>>504
CUIで作れるような簡単なゲームでも作るといいよ
俺はいつもヒットアンドブローを作るようにしている

507:デフォルトの名無しさん
10/04/27 22:01:56
構造体のメンバに順次アクセスする
ナイスな方法ってある?

508:デフォルトの名無しさん
10/04/27 22:10:36
char*でキャストして、1バイト毎に順次アクセスする

509:デフォルトの名無しさん
10/04/27 22:14:11
メンバの位置や型を配列にして保存しておいて
それでループでアクセス

まあ普通そんなことやるなでFAだが

510:デフォルトの名無しさん
10/04/28 15:43:35
>>507
unionを使うのが一番楽で上品

511:デフォルトの名無しさん
10/04/28 16:33:51
>>510
順次アクセスという言葉の意味がわかってないだろ
馬鹿は黙ってればいいのに

512:デフォルトの名無しさん
10/04/28 17:14:46
順次アクセスできない理由を教えてくれ天才

513:デフォルトの名無しさん
10/04/28 19:37:37
>>511
こういう感じでいけるっしょ。
typedef struct {
int a;
int b;
int c;
int d;
} hoge_t;

typedef union {
hoge_t u;
int l[4];
} chinko_t;

514:デフォルトの名無しさん
10/04/28 19:38:41
あ、int l[0] にしといた方が便利がいいな。

515:デフォルトの名無しさん
10/04/28 20:07:29
アラインメントが気になる
同じ型ならまず問題は無いだろうが、万が一があるしな

516:デフォルトの名無しさん
10/04/28 20:14:52
メリット皆無だし。

517:デフォルトの名無しさん
10/04/28 20:16:54
>>515
それを言い出したらそもそもunionの存在そのものが怖いよな。

>>516
誰もメリットの話なんかしてねーだろ

518:デフォルトの名無しさん
10/04/28 20:26:35
添え字でアクセスしたいだけなら
#define STFX(N,V) switch(N){case 0:struct.a=V;break;case 1:~}
で十分だし。

519:デフォルトの名無しさん
10/04/28 21:01:43
おいおい今日もまたCの連中はつまんねえことでもめてるよww

520:デフォルトの名無しさん
10/04/28 21:10:53
>>519
だよな、時代はD言語だろうに老頭児なC厨はオナニーでもしてろってのw

521:デフォルトの名無しさん
10/04/28 21:12:26
これだからC厨は・・・

522:デフォルトの名無しさん
10/04/28 21:12:59
D(笑)

523:デフォルトの名無しさん
10/04/28 21:14:18
おじいさまがたはFORTRANでも使っててください

524:デフォルトの名無しさん
10/04/28 21:14:28
老頭児って中国語か

525:デフォルトの名無しさん
10/04/28 21:18:30
おじいさまがたは LISP でも使ってください、
ん?

526:デフォルトの名無しさん
10/04/28 21:24:39
>>523,525
すまん、俺まだ20代だが両方とも会社で使ってるw

527:デフォルトの名無しさん
10/04/28 21:32:21
LISPは未だに超強力だからな。まあWindowsアプリに限って言うならC#の時代が来るかもしれない。囲い込みだしな
でもプログラムはWindowsアプリだけじゃないし、つーかDって誰が普及させるんだよw
世界中で使われてるCの牙城を崩す気ねーだろ
あとWebプログラミングのLLはこれからも生き残る

528:デフォルトの名無しさん
10/04/28 21:35:21
LISPはemacsとかあるからまぁ使う機会はそこそこあるかもしれんが
FORTRANを使う場面はまったく思い浮かばん
昔大学で実験に使って以来やってないから、もう文法もわがんね

529:デフォルトの名無しさん
10/04/28 21:49:20
順次アクセスとかそんなイレギュラーな使い方は普通しないし。

530:デフォルトの名無しさん
10/04/28 22:02:10
Fortranは大学ではまだつかってるところあるけど
Lispってemacsのマクロくらいしかないよ

って書こうとしてリロードして>>528を読んだ
たぶんほとんど同じものを見たのに出した答えが真逆で面白いなと思った

531:デフォルトの名無しさん
10/04/28 22:25:40
構造体の入れ子ってあまりよくないことなんでしょうか?(設計に問題あり?)


532:デフォルトの名無しさん
10/04/28 22:27:57
別に普通

533:ノラ
10/04/28 23:55:51
いま学校の課題で
do-while文を使って
1+2+3・・・というように数値を加算して表示し、
加算結果が300を超えたら表示して
処理を終了するというプログラムを組みたいのですが、
普段から授業ついていけなくて、よくわかりません
どなたか教えてください。お願いします

534:デフォルトの名無しさん
10/04/28 23:57:45
>>533
ここは入門スレなのであまり高度なことはお答えできません。

535:ノラ
10/04/29 00:00:38
>>534
どうしたらいいですか?

536:デフォルトの名無しさん
10/04/29 00:02:05
中学校の課題?

537:ノラ
10/04/29 00:03:53
>>536
いえ専門なんですが
全く授業についていけなくてですね・・・

538:デフォルトの名無しさん
10/04/29 00:03:56
>>535
スレリンク(tech板)

こちらへどうぞ

539:デフォルトの名無しさん
10/04/29 00:04:27
#include <stdio.h>

int
main(void)
{
  int i = 1;
  int sum = 0;

  do {
    sum += i++;
  } while (sum < 300);
  printf("%d\n", sum);

  return 0;
}


540:デフォルトの名無しさん
10/04/29 00:04:29
そういうときは美味しいカレーのレシピを書いて提出だろう

541:ノラ
10/04/29 00:12:06
>>539様ありがとうございます。
参考にしてがんばってみます

542:ノラ
10/04/29 00:14:24
>>539
sum入れないでもできますか?

543:デフォルトの名無しさん
10/04/29 00:16:16
ついていく気は無いようだwww

544:デフォルトの名無しさん
10/04/29 00:24:11
>>542 自分でやれよカス

545:デフォルトの名無しさん
10/04/29 00:52:38
>>542
#include <stdio.h>

int
main(void)
{
int i = 1;
do {
printf("%d\n", i * (i + 1) / 2);
i++;
} while (i * (i + 1) <= 600);
return 0;
}


546:デフォルトの名無しさん
10/04/29 00:55:13
>>542
結果を格納しておく変数が必要なわけ。
加算していって、それをどこに保持しておくの?って話になるでしょ?

だから、この場合は「sum」っていうy変数に入れてる。
別にgoukeiでもsでも、C言語の規則に従ってればなんでもいい。

547:デフォルトの名無しさん
10/04/29 00:55:55
>>545
綺麗だけど初心者には分かりづらいソースだなwwwwwwwwww

548:デフォルトの名無しさん
10/04/29 01:03:48
まて、少なくとも綺麗ではない

549:デフォルトの名無しさん
10/04/29 01:16:39
この手の問題は、答えが分かるのなら質問しない。つまり初めから論外なレベル
宿題スレじゃないんだからさ

550:デフォルトの名無しさん
10/04/29 02:39:15
ちょっと質問なんですけど。。。
Raw Socketってあるぢゃないですか?
私の開発環境はWindowsでVC++ 2008なので
Winsock2を使ってws2_32.libをリンクし、
socket(AF_INET,SOCK_RAW,IPPROTO_IP);
こうやって書くんだと思うんですが(違ったらまた勉強してきます)、
IPヘッダを作成するときにIPを偽装できるという記事を
拝見したことがあります。

その場合、IPというのは何のIPなのでしょうか?
プライベートIPですか?
グローバルIPですか?

仮にグローバルIPを返られるとした場合、
例えば携帯IPに変更することは可能なのですか?

もし可能なら大変なことになるのでそれは出来ないと思うのですが、
出来たとしたら掲示板などはどのような対策を施すのでしょうか?

■以下、板違い発言すみません。
私はC言語のほかにPerlやPHPなどCGIで掲示板などを作成してます。
もし上記に書いたようなグローバルIPを偽装するような行為があったとしたら
どのように防げばいいかわかりません・・・
できればそんなこと出来ないものだと願いたいものです。。。

551:デフォルトの名無しさん
10/04/29 06:42:02
>>550
スレチとか死ねよゴミ野郎

IPの偽装は現在は無理
一言でいうとヘッダに書いてあったIPに本当にそいつが送ってきたのか確認するから

それとグローバルIPですかプライベートIPですか?って質問も相当アホ



552:デフォルトの名無しさん
10/04/29 09:19:03
グローバルだよ (LAN内にサーバもあるならローカルでもいいけど)

携帯のふりもできるよ 掲示板は対策要らないよ
あんたの掲示板はTCPだろうから>>551が言うようにそのIPに対して問い合わせするわけだから
偽装された他人に問い合わせしても返事来ないでしょ

UDPで動く(昔のネットゲームとか?)ものなら がんばって通信内容もまねれば 
他人がゲームやってるときにちょっかい出せるかもしれんけど

553:デフォルトの名無しさん
10/04/29 15:12:39
すみません、矩形画像出したくて以下のを書いてみたんですが画像が表示されません。
誰かお願いします。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char fi[50];
float buff[128*128];
int nx = 128, ny = 128;
int i, j;
FILE *fp;

// 画像の初期化
for (i = 0 ; i < nx*ny ; i++)
buff[i] = 0;



554:デフォルトの名無しさん
10/04/29 15:14:47
// 矩形画像の作成
for (i = 32 ; i <= 96 ; i++) {
for(j = 32 ; j <= 96 ; j++) {
buff[i*nx+j] = 100;
}
}

// 画像の書き出し
printf( "Input new file name: " );
scanf( "%s", fi );
if ((fp = fopen ( fi, "wb")) == NULL) {
printf("Error: file open [%s].\n", fi);
exit (1);
}
fwrite(buff, sizeof(float), 128*128, fp);
fclose (fp);
}


555:デフォルトの名無しさん
10/04/29 15:22:34
どこそこがおかしいと言うレベルじゃなくめちゃくちゃなんだが
お前それ本とかみてやってそうなのか?

556:デフォルトの名無しさん
10/04/29 15:28:34
>>553
画像ヘッダをつけるかフォーマット指定してビューワに読み込ませれば表示できるかもしれない
ACDSEE とかそういうの

float 型の画像ってことはCTスキャンデータかな?
後輩だったりしてw

557:デフォルトの名無しさん
10/04/29 15:29:11
ウィンドウに絵を表示したいの?それとも画像ファイルを出力したいの?
前者ならまずウィンドウを作成しないと。
後者なら出力したい画像フォーマットに従ってデータを出力しないとダメだよ。

558:デフォルトの名無しさん
10/04/29 15:46:14
>>557
とりあえず raw形式でいいんじゃない?

559:デフォルトの名無しさん
10/04/29 16:11:29
釣りにつられたようだ

560:デフォルトの名無しさん
10/04/29 16:37:32
>float 型の画像ってことはCTスキャンデータかな?

先輩、今時CTのデータが128ってことはないでしょ 
ネマコードもないし DICOM形式でもない

561:デフォルトの名無しさん
10/04/30 09:51:52
ヘリカルスキャンCTの場合で、512x512x200くらいは平気でありそうだ。
つーか、float生データでも適切なツールを使えば表示はできるだろうけどね。
いずれにしても、Cの話じゃなく画像フォーマットの話というか仕様の解釈の話だ。

562:デフォルトの名無しさん
10/04/30 10:53:29
ヘリカルCTなら512x512x320くらいデフォだけど
型はshortだな

563:デフォルトの名無しさん
10/04/30 11:15:48
結局文型が業界にたくさん入ってきて保身に全力だからじゃないの?
あいつら技術的なこと分からないから技術持ってるベテランにいてもらうと邪魔なんだよ。
そいうやつらが外注管理とか客先交渉とかの技術的なこと分からなくてもできる仕事を創出してこの業界で生き残れるシステムを作ったんじゃないだろうか。
技術のない正社員はすぐ首にできるシステムになってないのがいけないんだと思うんだ。
だいたい技術職なのに技術にこだわってるやつを軽蔑する空気があるのはおかしいと思う。

564:デフォルトの名無しさん
10/04/30 11:18:53
誰かが言った、偉大なる素人集団だと。

565:デフォルトの名無しさん
10/04/30 12:00:27
そういう時、アメリカなら技術者だけが出て行って別会社を作る
たとえばintelの技術者が「もっとすごいCPUを作りたい」といって、独立して作った会社がAMD

ただし営業力がなくて負ける

566:デフォルトの名無しさん
10/04/30 13:33:12
でもさ、反論を覚悟で書くけど

技術が高くてもメシは食えないんだよね
でも営業が小ざかしいくらい上手いと技術がクソでも売れる
メインな部分どっかに丸投げでもOK 
宣伝の上手い声の大きいやつが勝つ


あと、技術持ってないやつが上にいたりすると楽だよね
「あ、それ2週間はかかります」とかどう考えても5分で終わる仕事でも平気でそんな事いってみたり
ある程度技術があるようならバレバレでもさ
(「そんなことしてるお前がクソなんだよ」って言われちゃうだろうな)

567:デフォルトの名無しさん
10/04/30 13:35:19
お前らマ板に帰れよ

568:デフォルトの名無しさん
10/04/30 13:39:55
>>566
上が技術だとある意味もっと楽だぞ。
こっちの話がちゃんと伝わるから、更に上にリソースの確保をきちんと交渉してくれる。
尤も、弊社の場合No.2まで技術系だから突っ込まれたときはやばいw

569:デフォルトの名無しさん
10/04/30 13:40:35
いい加減巣に帰れよ

570:デフォルトの名無しさん
10/04/30 13:41:26
>>569
スレ違いの雑談と言う意味ではあんたも同罪。

で、Cの初歩的な質問未だ?w

571:デフォルトの名無しさん
10/04/30 13:43:10
reallocって失敗したら元のデータはどこかへ消えてしまうんですか?
そのあたりがよくわかりません

572:デフォルトの名無しさん
10/04/30 14:07:53
>>571
お前にわかる必要など無い

573:デフォルトの名無しさん
10/04/30 14:09:40
>>571
宇宙の法則がみだれるからな・・・

574:デフォルトの名無しさん
10/04/30 14:54:33
>>571
大丈夫。realloc()はメモリ確保に成功しない限り元の領域は解放しない。
つまり、使う側が間抜けでない限りどこにも消えはしない。

575:デフォルトの名無しさん
10/04/30 15:10:13
>>574
回答ありがとうございます
reallocに与えるアドレスをとっておいて、reallocがNULLを返したらそっちを取り扱えばいいってことですね

とはいえ今まで一度もmalloc系が失敗するとこをみたことないんですけどね

576:デフォルトの名無しさん
10/04/30 15:57:46
>>575
いつ失敗するんだろうと思って延々mallocをしてみるのが普通のマ。

577:デフォルトの名無しさん
10/04/30 15:59:32
まぁ確かに。標準設定のままのLinuxだと楽観的メモリ管理を採用しているから
以上に大きな値を指定しない限り、メモリが足りようと足りなかろうとNULLは返さないからね。

で、実際に使おうとしたときに足りなくなるとプロセス落として知らん顔w

578:デフォルトの名無しさん
10/04/30 16:09:09
カーネルパラメータいじる前にメモリを増設します

579:デフォルトの名無しさん
10/04/30 16:12:07
じゃあ俺は64bitLinuxにしてかつスワップもりもりにする

580:デフォルトの名無しさん
10/04/30 16:17:50
Linuxのソースを改造してメモリ管理を改善させます。

581:デフォルトの名無しさん
10/04/30 16:20:17
なにを改善するんだろ。楽観的メモリ管理をやめるために改造するはずはないし

582:デフォルトの名無しさん
10/04/30 16:24:21
楽観的メモリ管理をやめたいだけなら設定変更するだけじゃなかったっけ?
まぁ、Linux板向けの話だね。

583:デフォルトの名無しさん
10/04/30 18:39:33
/proc/sys/vm/overcommit_memory

584:側近中の側近 ◆0351148456
10/04/30 19:19:45
>>575
(っ´▽`)っ いや、異常終了にしたほうがいいんじゃね?
alloc系がエラー返すって相当やばいから、処理続行するのは危険だね。

585:デフォルトの名無しさん
10/04/30 20:19:21
reallocしたい場面にもかかわらず、reallocに失敗しても続行できる場面が想像しがたいけど、
続行できるのなら続行してもいいと思うよ。
ほんとに必要な場面で失敗したなら異常終了で。

586:デフォルトの名無しさん
10/04/30 20:23:22
そういう場面では、キャッシュとして確保しっぱなしのメモリを開放とかじゃないかなあ・・・

587:デフォルトの名無しさん
10/04/30 21:20:56
つか、実際そういう時って
固まっちゃって動かなくて、引き続き他の動作もクソもないよな


次ページ
最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch