[表示 : 全て 最新50 1-99 101- 201- 301- 401- 2chのread.cgiへ]
Update time : 05/10 01:28 / Filesize : 110 KB / Number-of Response : 467
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C言語なら俺に聞け(入門編)Part 61



1 名前:デフォルトの名無しさん mailto:sage [2010/03/05(金) 23:27:18 ]
C言語の*入門者*向け解説スレッドです。
★前スレ
C言語なら俺に聞け(入門編)Part 60
pc12.2ch.net/test/read.cgi/tech/1264920499/
★過去スレ
makimo.to:8000/cgi-bin/search/search.cgi?q=%82b%8C%BE%8C%EA%82%C8%82%E7%89%B4%82%C9%95%B7%82%AF&andor=AND&sf=0&H=&view=table&D=tech&shw=5000
★初心者、初級者の方は他の質問スレのほうが良いかもしれません。
例えば
【初心者歓迎】C/C++室 Ver.72【環境依存OK】
pc12.2ch.net/test/read.cgi/tech/1267775473/
とか
★教えて欲しいのではなく宿題を丸投げしたいだけなら
↓宿題スレ↓へ行ってください。
C/C++の宿題片付けます 134代目
pc12.2ch.net/test/read.cgi/tech/1263824755/
★C++言語についてはなるべく聞かないでください。C++対応明記スレへどうぞ
★分からない事をなるべく詳しく書いて下さい。
★ソースコードを晒すと答えやすくなるかもしれません。
  # 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること
  # サイズが大きい場合は宿題スレのアップローダ等を利用してください
★開発環境や動作環境も晒すと答えが早いかもしれません。
★質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。

413 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 01:11:33 ]
>>410
> buff=(char *)realloc(buff, sizeof(char) * 20);という具合に。
出たよ。メモリ確保できないときにリークが確定するパターン。
初心者に realloc() 教えるとすぐこれをやらかす。

414 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 01:16:08 ]
鬼の首でも取ったのか?
喜びすぎだろ

415 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 01:20:57 ]
喜んでるわけが無いだろjk
うんざりしてるんだよ。

416 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 02:32:19 ]
#include <stdio.h>
#include <stdlib.h>
// 構造体 B
typedef struct tagB { int max_size; char* buff; } B;

// B を初期化する命令
void B_init( B* b ) { b->max_size=10; b->buff =(char*)malloc(sizeof(char) * b->max_size); }

// B のメモリを10ふやす命令
void B_realloc( B* b ) { b->max_size += 10; b->buff = (char*)realloc( b->buff, sizeof(char) * b->max_size ); }

// Bに char を一文字セーブする命令 ( B の buff が短かったら自動的に伸ばしてくれる )
void B_write( B* b, char c, int index ) { if( index >= b->max_size ){ B_realloc(b); B_write( b, c, index ); } b->buff[index] = c; }

// Bから char を一文字ロードする命令 ( B の buff が短かったら自動的に伸ばしてくれる ) 
char B_read ( B* b, int index ) { if( index >= b->max_size ){ B_realloc( b ); B_read( b,index ); } return( b->buff[index] ); }

void main() { B b; B_init( &b ); B_write( &b, 'A', 12345 ); printf("%c\n", B_read( &b, 12345 ) ); }

おこられそう…w(^_^

417 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 02:52:10 ]
>>416
怒りはしないが、ダメダメ。
ロードする関数でrealloc()しても、増えた領域に何にも書いてないから不定値が返るぞ。
それに、セーブする方も任意のindexを指定できるのに一度に伸ばせるのが高々10文字だから簡単に範囲外書き込みになってしまう。
それに、sizeof(char)なんて無意味なことは書くべきじゃない。

418 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 02:55:55 ]
>>413
出たよ。問題の本質と関係ない話をする奴。
buffの宣言がないじゃん、と言ってるのと同レベルだぜそれ。
初心者じゃなくなったと思い込んでる初心者はすぐこれをやらかす。

419 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 02:56:52 ]
そもそも、メモリ確保ができなくなる心配をする前にすることがあるだろうと。

420 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 02:57:08 ]
その程度のサイズでrealloc使うとか、何の冗談だよw

421 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 03:00:21 ]
足りなければ倍にするというやんちゃな方式が時として功を奏することもあるよ
とりあえず、ポインタを元にアロケーションしているサイズを知ることはできないので他で管理しましょう

>>420
ええと。



422 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 09:12:57 ]
どうしても必要ならともかく、入門レベルでrealloc使わせるのはどうかと思うが。
余裕をもとって大きめに領域確保するほうがよっぽどマシ。

423 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 09:15:29 ]
>>413
すぐそのあとに、if (buff == NULL) exit(1); と書けば問題なし。
メモリ不足なら、ほかのところだってまともに動くわけないんだから。

424 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 09:32:48 ]
>>422
それはそれでイヤン

425 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 11:07:20 ]
>>424
サイズをオーバーするかどうかちゃんとチェックするならありじゃね?

426 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 14:55:30 ]
>>425
オーバーしそうになったらどうすんの?

427 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 15:50:24 ]
>>426
・ごめんなさい、私には無理です
・オーバーする分はなかったことにしていいよね

どちらでもお好きに。

428 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 16:08:53 ]
一行が長いテキストファイルを開くと落ちるエディタ
一行が長いと後ろのほうが切り捨てられるエディタ

どっちもいやだなぁ

429 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 16:10:43 ]
4G以上のファイルとかどうやって扱ってんのか気になる

430 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 16:27:26 ]
>>429
4GB以上のファイルを普通に扱える環境なら、64ビットアドレッシングで使うのが当たり前だから特に工夫は要らないよ。
32ビット環境で扱いたいなら、一度に全部開かなければいいだけだからやはり、4GB以上だからといって別段大仰な手間は要らない。

>>428
初心者が作るのなら、取り敢えずそれでもいいのでは? まさか、そのまま保存するわけでもあるまいし。

431 名前:デフォルトの名無しさん [2010/03/19(金) 19:50:57 ]
文字配列についてお尋ねします

char buf[6] = {'A', 'B', 'C', 'D', 'E', '\0'};
と宣言したとします。

このとき
buf[1]は 'B'が格納されており文字コードが例えば66だとします
buf[1]は数値そのものであるので、if(buf[1] == 66)もしくはif(buf[1] == 'B')のような比較が可能です。(ですよね?)
ここでbufとするとABCDEという文字列を表すことになりますが、このときbuf自体の数値は
bufのアドレスが入っています。(ですよね?)

ここで疑問なのですが、bufは一体どこのアドレスが入っているのでしょうか?
例えば、buf[0]のアドレスと同じものであればAとしか表示されないはずです。
ABCDE\0をもってくるにはbuf[0]からbuf[5]までのアドレスが必要なはずです。

buf自体はアドレスの開始地点で終端文字の\0が現れる部分までのオフセットを割りだし
そのアドレスをすべて与えて文字列を表示しているということでよろしいでしょうか?
回答よろしくお願いします。



432 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:01:01 ]
>>431
buf と等価なのは &buf[0]

433 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:04:08 ]
>>431
だいたい合ってるが、1点だけ。

> ここでbufとするとABCDEという文字列を表すことになりますが、
bufがABCDEという文字列を表しているわけではない。
あくまで文字列の先頭のアドレスを保持しているにすぎない。
buf == &(buf[0])

puts(buf)で"ABCDE"と表示されるのは、以下のような処理をしているため。
for(char *p = buf; *p != '\0'; p++) { *pを出力; }

434 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:07:07 ]
>>431
配列は配列であってポインタじゃない

435 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:10:42 ]
char buf[] = {'h', 'o', 'g', 'e', '\0'}
char *p = buf;

buf

'h' 'o' 'g' 'e' '\0'

0x00..... ← p

436 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:13:39 ]
グダグダ言ってないでデバッガで変数見りゃいっぱつだろうが

437 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:14:09 ]
>>431
>ここでbufとするとABCDEという文字列を表すことになりますが
ここでってどこだよw

438 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 20:26:53 ]
>431
言っていることはその通り何だけど
NUL('\0')終端文字列はNULが現れるまでを文字列とみなすから表示させたい最初の文字のアドレスを渡すだけでいいのよ
あなたにお薦めなサンプルプログラム

#include <stdio.h>
#include <string.h>

int
my_print(char const*str)
{
  size_t i;
  for ( i = 1; i < str[0]+1; ++i ) {
    putchar(str[i]);
  }
  return i-2;
}
int
main(int argc, char **argv)
{
  char foo[6] = {'a', 'b', 'c', 'd', 'e', '\0'};
  char bar[16] = {'a', 'b', 'c', 'd', 'e'};
  char baz[] = {3, 'b', 'a', 'z'};
  memset(bar+5, '\100', 10); /* ゴミを入れる */
  bar[15] = '\0'; /* NUL終端させる */
  printf("%s\n", foo);
  printf("%s\n", &foo[0]);
  printf("%s\n", &foo[3]);
  printf("%s\n", bar);
  my_print(baz);
  return 0;
}

439 名前:デフォルトの名無しさん [2010/03/19(金) 21:22:55 ]
配列はメモリ上連続しているので、先頭アドレスと型がわかれば計算で出ます。
コンパイラは &buf[5] を &buf[0] + (5 * sizeof(char)) と捉えます。

440 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 21:33:35 ]
プログラミングに使う単語って英語ですか?

441 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 21:37:20 ]
基本的には



442 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 21:43:31 ]
皆さんは英語ペラペラですか?

443 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 21:44:01 ]
My English is poor.

444 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:17:57 ]
>>442
fuck u

445 名前:431 [2010/03/19(金) 22:18:43 ]
>>433
buf自体がが先頭アドレスなのは↓に書いたように知ってます
>buf自体はアドレスの開始地点
結局全部
for(char *p = buf; *p != '\0'; p++) { *pを出力; }
これやってるだけなんですね…

446 名前:431 [2010/03/19(金) 22:24:21 ]
>>439

buf[5]を例えばprintfするときはオフセットで
文字列を全部表示するときはポインタをズラす方法で表示しているのですか?

for(char *p = buf; *p != '\0'; p++) { *pを出力; }
このようにポインタをズラしているのか、
それとも
&buf[5] を &buf[0] + (5 * sizeof(char))
のようにオフセットで計算しているのか
内部の処理はどっちなんでしょうか?

それが>>431の質問で一番知りたいことなんですが


447 名前:431 [2010/03/19(金) 22:26:02 ]
>>436
オフセットで計算したものか、ポインタをズラしたものなのか
格納されたアドレス見るだけじゃわからないんですよ…

448 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:26:32 ]
どういう風にprintfを作るかなんて決まってないしコンパイラメーカーが勝手にやってるだけだよ
きっと、前者だろうなって気はするけど

449 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:27:39 ]
前者な気がする

450 名前:431 [2010/03/19(金) 22:28:24 ]
>>448
そうなんですか…
どっちが主流なのか知りたかったのですが(速度とかいろんな意味で)

451 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:30:39 ]
そんなこと知ってどうすんだろ



452 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:31:24 ]
速度とかそれこそきまってねえだろ
おまえはなにか?コンパイラは全て同じ中身じゃないといけないと思ってんのか?主流ってなんだ?どの環境の主流だ?
クソして寝ろや

453 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:33:28 ]
>>450
もう答えは出てるだろう。文字列探索程度のコストを気にするより
もっと他の所の速度を気にしろ。

454 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 22:35:29 ]
簡単なプログラムつくって、最適化全部はずしてバイナリを逆アセンブルして追っかけてみれば?
ペンティアム以降になると急に難しくなるから、LSICの試食版あたりからははじめて
あるいはgccならprintfもソースみれるよ

そうやって3,4個調べてみれば主流もわかるんじゃね

455 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:38:50 ]
robot C わかる人いる?

456 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:41:38 ]
ボクは個人的には
char c[1234]
ってのを

putchar( c[0] ); putchar( c[1] ); putchar( c[2] ); putchar( c[3] ); putchar( c[4] ); putchar( c[5] ); 〜〜〜ずーっとつづく
って書くよりも

char* p=c;
putchar( *p++ ); putchar( *p++ ); putchar( *p++ ); putchar( *p++ ); putchar( *p++ );  〜〜〜ずーっとつづく
って書く方が、コピペが楽なので好きですw


457 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:43:53 ]


458 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:44:02 ]
頭おかしいのかおまえ

459 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:52:53 ]
俺がコンパイラなら syntax error 出すわな

460 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:53:21 ]
最終的にはsystem callを追っかけてlibcやkernelに入りそうだな

461 名前:デフォルトの名無しさん mailto:sage [2010/03/19(金) 23:59:13 ]
int 21Hで終わりでいいじゃん



462 名前:デフォルトの名無しさん mailto:sage [2010/03/20(土) 00:06:12 ]
char c[1234];
ってのは、使うときは putchar( c[3] ) みたいにして使います。 c[0] なら最初の文字、c[3]なら3番目の文字です。  

&c[3]  みたいに、頭に&マークをつけると、このデータがメモリのどこに書かれてるかがわかります。配列の先頭が、メモリのどこにあるかは &c[0] でわかります。

使うときにカッコを取って c って書くと、 &c[0] って書いたときと同じ数字がわかります。 この c そのものを c++ ってやって一個増やすと、
char型の配列なら、char一個分だけメモリをさしてる場所が増えます。 だから c++ とすると、つぎに使うときは c は &c[1] といういみになります。

int型の配列なら、int i[1234];

463 名前:デフォルトの名無しさん mailto:sage [2010/03/20(土) 00:08:19 ]
i++ で int の大きさ分だけ増えます。 

や〜めた

464 名前:デフォルトの名無しさん mailto:sage [2010/03/20(土) 00:14:26 ]
>462
またまたご冗談を

465 名前:デフォルトの名無しさん mailto:sage [2010/03/20(土) 00:19:03 ]
>>462
そんなコンパイラなんて…
あるかもしれないが規格無視じゃないか

466 名前:デフォルトの名無しさん mailto:sage [2010/03/20(土) 00:27:03 ]
>>462
その場合cは定数だからc++なんて出来ないだろアホ






[ 新着レスの取得/表示 (agate) ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<110KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef