C言語なら俺に聞け( ..
[2ch|▼Menu]
431:デフォルトの名無しさん
10/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:デフォルトの名無しさん
10/03/19 20:01:01
>>431
buf と等価なのは &buf[0]

433:デフォルトの名無しさん
10/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:デフォルトの名無しさん
10/03/19 20:07:07
>>431
配列は配列であってポインタじゃない

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

buf

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

0x00..... ← p

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

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

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

440:デフォルトの名無しさん
10/03/19 21:33:35
プログラミングに使う単語って英語ですか?

441:デフォルトの名無しさん
10/03/19 21:37:20
基本的には

442:デフォルトの名無しさん
10/03/19 21:43:31
皆さんは英語ペラペラですか?

443:デフォルトの名無しさん
10/03/19 21:44:01
My English is poor.

444:デフォルトの名無しさん
10/03/19 22:17:57
>>442
fuck u

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

446:431
10/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
10/03/19 22:26:02
>>436
オフセットで計算したものか、ポインタをズラしたものなのか
格納されたアドレス見るだけじゃわからないんですよ…

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

449:デフォルトの名無しさん
10/03/19 22:27:39
前者な気がする

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

451:デフォルトの名無しさん
10/03/19 22:30:39
そんなこと知ってどうすんだろ

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

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

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

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

455:デフォルトの名無しさん
10/03/19 23:38:50
robot C わかる人いる?

456:デフォルトの名無しさん
10/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:デフォルトの名無しさん
10/03/19 23:43:53


458:デフォルトの名無しさん
10/03/19 23:44:02
頭おかしいのかおまえ

459:デフォルトの名無しさん
10/03/19 23:52:53
俺がコンパイラなら syntax error 出すわな

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

461:デフォルトの名無しさん
10/03/19 23:59:13
int 21Hで終わりでいいじゃん

462:デフォルトの名無しさん
10/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:デフォルトの名無しさん
10/03/20 00:08:19
i++ で int の大きさ分だけ増えます。 

や〜めた

464:デフォルトの名無しさん
10/03/20 00:14:26
>462
またまたご冗談を

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

466:デフォルトの名無しさん
10/03/20 00:27:03
>>462
その場合cは定数だからc++なんて出来ないだろアホ


最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5399日前に更新/110 KB
担当:undef