1 :
デフォルトの名無しさん :
03/06/20 13:20 教えてください
2 :
デフォルトの名無しさん :03/06/20 13:20
さあな。
*
単発質問断固反対
5 :
デフォルトの名無しさん :03/06/20 13:23
6 :
デフォルトの名無しさん :03/06/20 13:24
それにはまずC言語の変数や構造体どういう風に記録されているかから説明しなければならない。
8 :
デフォルトの名無しさん :03/06/20 13:25
削除依頼完了
プログラム板いけつったじゃん
スレ立てろと書いてあったか?
スレたてちゃだめなの?
ちーちゃんのポインタ
>この板はプログラムを作る人のための板です。 >あらゆる質問はまずすれ立てるまでもない質問はここでスレにしてください。
初心者でしりませんでしたすいません
ハァハァ いいよ、いいよぉ〜
__∧_∧_ |( ^^ )| <寝るぽ(^^) |\⌒⌒⌒\ \ |⌒⌒⌒~| 山崎渉 ~ ̄ ̄ ̄ ̄
__∧_∧_ |( ^^ )| <寝るぽ(^^) |\⌒⌒⌒\ \ |⌒⌒⌒~| 山崎渉 ~ ̄ ̄ ̄ ̄
(^^)
(⌒V⌒) │ ^ ^ │<これからも僕を応援して下さいね(^^)。 ⊂| |つ (_)(_) 山崎パン
22 :
デフォルトの名無しさん :03/08/16 10:48
タグみたいなもんです
23 :
デフォルトの名無しさん :03/08/16 11:05
ポラロイドカメラの「ポラロイド」ってなんですか?
25 :
デフォルトの名無しさん :03/08/16 14:24
僕はなんで童貞なんですか?
27 :
デフォルトの名無しさん :03/08/27 11:02
ドッグタグみたいなヤツだな
まず、坂村健の化身・実身モデルを学べ。
ペンの先から赤い光がでて、プレゼンのスクリーンを指すやつ
ポインタとは何かを理解するより、先にポインタで何ができるかを学んだ方がいい。 理論は後からついてくる。 まず最初に覚えるべきポインタの利用方法は、関数の引数への代入。 関数は引数に入力、返値に出力という構造が基本だが、これだと出力は一つしか持てない。 そこで本来入力としての引数にポインタを使えば、引数も出力として扱うことができる。 なぜそうなるのか?という疑問を持ったなら、調べてみるといい。 アドレス渡しと値渡しの違いが分かれば、ポインタの仕組みが理解できてくるだろう。
やつぱし初心者はポインタで悩むんだね。
32 :
デフォルトの名無しさん :03/09/01 23:08
Cカップのボインタンって何ですか?
34 :
デフォルトの名無しさん :03/09/01 23:27
>>1 それとあと構造体でみんな挫折するそうです。
ポインタのポインタとか、ポインタを返す関数へのポインタとか、 そういうのが出てくると死ねるそうです。
上級者にとって、初心者が何故ポインタが理解できないかを 理解することは有益だろうか?
37 :
デフォルトの名無しさん :03/09/01 23:58
初心者がC言語からはじめるのが間違い アセンブラから覚えろ そしたらこんなアホな質問はなくなる
39 :
デフォルトの名無しさん :03/09/02 00:06
初心者が口から牛乳飲むのが間違い 鼻から飲め そしたらいざというとき口から出せる
LPPPPPPPPPPPPPPCSTR lppppppppppppppString;
>>30 C の関数は全て値渡しに過ぎない。
ポインタ値と言う値を渡すだけ。
ぬるぽいんた
43 :
デフォルトの名無しさん :03/09/20 21:59
>>41 って、本に書いてあったから、真似して言ってみたかったんだろ?
もう一度
>>30 を読み返せ。っていっても、オマエには理解不能か(w
>>43 終了させたいならあげるなよ。
45 :
supermathmania ◆ViEu89Okng :03/09/23 17:11
Re:>41 確かにポインタ値渡しだが、ポインタ型変数で何が出来るかを踏まえて説明して欲しいものだ。
46 :
デフォルトの名無しさん :03/09/23 17:25
c#とC++と ObjectiveC との切り替えだよ >>1
ちょっと太目の女の子の胸についているのだよ。
ぬるぽ はポインタですよ。
javaはぼいんたん無いですよー。 gj台追いf;亜jんhきgf;あきgふぁhにごれ
ポウィンタ
52 :
デフォルトの名無しさん :03/11/27 17:24
>>50 なんで、Javaにポインタはないんですか?
>>52 ぬーんC言語が糞だからだよ
るるるむしろC言語のポインタが糞だと言ったほうがいい
ぽっぽーつまり要するにC言語のポインタはポインタと自称しているわりに余計な機能が付きすぎてるってこった
だからJava様はそんなヘポインタと一緒にされたくなかったわけなのです
>>52 ポインタはあるんだけどポインタと言いがたい状況だ。
アドレスを参照する具合な感じだからポインタを扱ってる用に見えないだけではないのかな?
ポインタは定義をきちんとやろうとするとドツボに嵌る。 アセンブラから入った人は素直にアドレス型だとわかる。 アセンブラやらない今の人は、ポインタ型=クラスだと 思い込みがちだが、全然違うもの。構造体へのポインタ型 と代入操作に対する扱いにくさは似ていなくも無いが。
>>55 経験が物をいうんじゃないか?
いくべんも失敗して理解しる
ポインタ型ってさー int型のポインタ型とかchar型のポイント型とかあって わけわかんねーよ! アセンブラのほうがよっぽど素直だ
>>57 指し示す先の位置の他に、指し示す先がどんな種類のデータか?と言う情報があるだけじゃん。
>>57 じゃあアセンブラしてください。
int型のポインタ型は変
int型のポインタとは言うがポインタ型っておかしくないか?
ポインタは型では無いのでわけわかめにはなりません
キャスト式に使えるから型は型でしょ。構造体も。
>>60 そういう風に言うならば long型 じゃね?
>>59 >ポインタは型では無いのでわけわかめにはなりません
ポインタ型は存在する訳で(ry
>>62 略してないよ全然w
あぃ、あるんですね。
わかりました
64 :
デフォルトの名無しさん :03/11/28 15:37
char **p; int a,b,c,…; *(p+0) = &a; *(p+1) = &b; *(p+2) = &c; … これ、領域も確保してなくとも*(p+n)には代入していけるのですか?
できません
□を変数を格納する箱だと思ってください
面倒くさいので全部 int で逝きます
a
□ int型 a です
*p a
□─→□
int型をさすポインタも変数であるわけね
**pp *p a
□─→□─→□
**になると int型をさすポインタをさすポインタ になります。
で、
>>64 だと *p が何処にあるか指定されて無いから代入できないわけ
代入できても暴走する可能性がある
>>64 どこか有効な領域を指していれば出来る。
# 意図したものとは恐ろしく違うだろうがな。(w
>>67 出来るかも知れないけどさぁ・・・やばくないかなぁ〜^^;
int **p; p = (int **)malloc(sizeof(int *)) p = &a[0]; p+1 = (int **)malloc(sizeof(int *)) p+1 = &b[0]; これで良いですか?
>>69 めちゃくちゃ.
mallocはHeap領域にあるサイズの領域を確保してその先頭アドレスを
返す。そのアドレス値はプログラマは知らなくてもいい暗号アドレス。
それをp=&a[0]というヒープ領域には無い、つまりmallocで確保された
領域とは無関係な配列変数aの先頭アドレスで置き換えてしまっている。
mallocで得られたアドレスをこうして潰してしまうと、その値は永遠に
知る由もなくなる。ヒープで確保されたメモリはこうして開放されること
なく、プログラム終了までゾンビ状態でメモリリソースをただ圧迫する
だけの存在になってしまう。
やりたいことはpというint*型の配列へのポインタが指すp[0](int *型
変数)に&a[0]というアドレスを入れてやりたいわけね。
つまり
p[0]=&a[0];(もしくは*p=&a[0];)
p[1]=&b[0];(もしくは*(p+1)=&b[0];)
がより正しいということになる。
p+1=(int **)malloc....は滅茶苦茶
でコンパイルも通らない筈(アドレス値は左辺値にならない)
C言語のポインタって食べられますか?
>>73 C言語のポインタは垂らす調味料なので、少量しか食べられません。
たくさん食べると体調不良になります。
>>71 まさにその通りだけど、初心者にはわけわからんと思われ。
>>71 これについて考えるので、ちょっと時間を下さい。
また明日レスします。
>>76 無理に背伸びしなくていい
簡単に言うと
「出来るか」「出来ないか」だろ?
>>64 の疑問は「出来ない」の方、解決法を見出せばわからなかったことが解るかもしてないぜ
int X = 5; char Y = 'a'; 宣言した変数をメモリ上でイメージすると下記になる。 メモリ番地 変数名(別名) データ 1番地 (int) X 5 2番地 (char)Y 'a' 3番地・・・ (積んでいるメモリによって総番地数は異なる) そこで int *a = &x とした場合、int型のポインタ(番地)を扱う変数にX(変数名)の番地を入れるという意味になる。 その結果、ポインタ(番地)を扱う変数は a → 1番地 *a → aの指し示す番地の内容(5)を表す。 のように使われる。 そして、 char *b = z においては、charとintでデータを入れるのに要するメモリ数が異なるためこれは実行できない。
第二段。
int p[n]のpはポインタ定数です。
イメージとしては
メモリ番地 変数名 データ
1番地 p[0]==p+0番地 1
3番地 p[1]==p+1番地 2
5番地 p[2]==p+2番地 3
です。
pは1番地を指すポインタ定数です。
それ故、(ありえない話ですが、メモリ内が仮に空だと仮定すると)
int *pp = p[0];とすると、
*ppのpp=00000001番地
p[0]=00000001番地
*ppのpp+1=00000003番地
p[1]=00000003番地
となります。
>>78 で説明したようにcharとintでは使用するメモリ領域が違います。
具体的に申しますと、charは1byte、intは2byte使用します。
それはアセンブラや機械語をされたかたはご存知かと思いますが、実際には
1番地 2番地
3番地 4番地
・・・・
のようにメモリが論理的に配置されている為、上記にあわせると
1番地 2番地
(int型の数値)5
3番地 4番地
'5' 'X' ※3,4番地は別のchar型の変数領域
となります。一番地につき1byteです。
第3弾
mallocはイメージとしてはメモリ内に固定領域をプログラマが任意に取ることができます。
malloc(sizeof(int))ならばint型のメモリ上のサイズは2byteですので、2byte分のメモリを
開いている領域に確保します。
0番地 変数Xの値が入っている
1番地 空
2番地 変数Zの値が入っている
3番地 空
4番地 空
上記のようにメモリが開いていたと仮定するならば、
>>79 の各型のメモリ使用を考慮して、1番地では1byteしか空いていないので
3,4番地の連続領域を利用します。
そしてmalloc(sizeof(int))の戻り値として「3番地」というポインタ(番地)を
返します。
そのため、受け取り側は
int *pointer;
pointer = malloc(sizeof(int));
と受け取ります。
ところが、
>>69 のような場合、
pointerには3番地が入っていますので、(左辺に計算云々は置いておいて)
3番地+1(1は左辺の変数のサイズにより可変。intの場合は2番地ずつ)=5番地となります。
>>69 を例にしますと、
pointer + 1;
pointer = (*int)(malloc(sizeof(int));
であり、論理的には問題ないと思います。
しかし、現実にはこのように何が入っているかわからないような危険な事は避けた方が良いでしょう。
くそスレだったはずなのに、いつのまにかマジレスで埋まり始めたね。
第4弾
ちなみに
*pointer;
pointer = (*int)malloc(sizeof(int));
の(*int)はキャスト演算子です。
キャスト演算子とは右辺の値をキャスト(変換)して左辺に代入します。
int n = 0;
float f = 1.5;
n = (int)f;
としますと、floatで表された浮動小数点が小数点以下で切り捨てられ
n == 1 となります。
あとは構造体の説明が終われば
>>69 さんもばっちりですね。
第5弾 構造体について。 構造体とはイメージとしてユーザー定義の変数の型です。 struct おいらが自由に作る型 rei{ char name; int age; char address[50]; struct おいらが自由に作る型 *free; }; 今まで利用していたint型やchar型というのはC言語側が勝手に作った型で使い勝手が悪い事があります。 例えば、double以上の精度の浮動少数(バイト数が多いほど高精度)を扱いたい場合や、違う型を複数持つ多次元配列などです。 そういう時に「既存の型を組み合わせて自分の好きな型を作れれば・・・」という期待に答え(?) 構造体が実現されています。 上記の例は複数人いる人のデータを入れる変数の型に使えますよね。 ポインタを使う場合も今までのポインタ変数と同じく、 struct 自分で作った型 *pointerとしてその構造体の位置を示すポインタを入れる変数を作る事ができます。 また、構造体では既存の型のように struct おいらが自由に作る型 任意の変数名 でいくらでも同じ型の変数を作る事ができます。 なお、構造体の中の自分の型と同じポインタは簡単に説明すると、「リスト構造」などを利用する際、構造体の中で自分と同じ構造の ポインタを使うと色々便利なことができるのです。(詳細は別途調べてね♪)
うわーん、名前の番号がずれてる・・・ ・・・ ・・・ ・・・ ごめんなさい、飽きました。 間違っていたら本職のプログラマさん訂正してやってください。 学生さんは学校の卒業制作で忙しいのでJava初心者スレに戻ります。 じゃね。
#include <stdio.h> #include <stdlib.h> #define test_size 5 main(){ char a[test_size] = "a_ary"; char b[test_size] = "b_ary"; char c[test_size] = "c_ary"; char d[test_size] = "d_ary"; char e[test_size] = "e_ary"; char f[test_size] = "f_ary"; char g[test_size] = "g_ary"; char **p; int m,n;
*(p+0) = (char *)malloc(sizeof(char *)); *(p+0) = &a[0]; *(p+1) = (char *)malloc(sizeof(char *)); *(p+1) = &f[0]; *(p+2) = (char *)malloc(sizeof(char *)); *(p+2) = &c[0]; for(m=0;m<3;m++){ /*3登録*/ for(n=0;n<5;n++) /*1登録につき5文字*/ printf("%c",*(*(p+m) + n)); printf("\n"); } return 0; } 実行結果 >*.exe a_ary f_ary c_ary
>>85 malloc確保領域をつかっていない状態に
してしまいました。もう一度考え直します。
アドレス番地[ 格納数値 ] char ***p char str_a[str_size] = "str_a group0 " index_groupX group1_strX strX p+0[ *(p+0) ] p+1[ *(p+1) ] -> *(p+1) [ *(*p+1) ] . *(p+1) + 1[ *(*(p+1) + 1) = str_X] -> *(*(p+1) + 1) == str_X[ *(*(*(p+1) + 1)) == str_X[0] ] *(*(p+1) + 1) + 1 [ *(*(*(p+1) + 1) + 1) == str_X[1] ]
/* index_groupX group0_strX str_a str_f str_c group1_strX str_b str_c str_g */ #include <stdio.h> #include <stdlib.h> #define str_size 16 main(){ char str_a[str_size] = "str_a group0 "; char str_b[str_size] = "str_b group1 "; char str_c[str_size] = "str_c group0,1"; char str_d[str_size] = "str_d other "; char str_e[str_size] = "str_e other "; char str_f[str_size] = "str_f group0 "; char str_g[str_size] = "str_g group1 "; char*** p; int l,m,n;
/* index_groupX group0〜1の領域 */ p = (char ***)calloc(2,sizeof(char **)); /* group0,1_strX strXの3つ分の領域 */ *(p+0) = (char **)calloc(3,sizeof(char *)); *(p+1) = (char **)calloc(3,sizeof(char *)); /* group0にstrXを登録 */ *((*p+0) + 0)=str_a; *((*p+0) + 1)=str_f; *((*p+0) + 2)=str_c; /* group1にstrXを登録 */ *(*(p+1) + 0)=str_b; *(*(p+1) + 1)=str_c; *(*(p+1) + 2)=str_g;
for(l=0;l<2;l++){ /* group0〜1 */ printf("group:%d\n",l); for(m=0;m<3;m++){ /* 1つのgroupにつき3つのstrX */ printf(" ",m); for(n=0;n<str_size;n++){ /* 1つのstrにつきstr_sizeの文字数 */ printf("%c",*(*(*(p+l) + m) + n)); } printf("\n"); } printf("\n"); printf("\n"); } return 0; }
実行結果 group:0 str_a group0 str_f group0 str_c group0,1 group:1 str_b group1 str_c group0,1 str_g group1
>>88-92 このcalloc領域は、有効に活用されているでしょうか?
その他にも何か気付いた事があれば、レスして欲しいです。
char ***p; このように宣言した場合、 &p番地に(char ***)型のp領域が生成される。 しかし、&(p+1)番地に(char ***)型のp+1領域は生成されない。 ょってpは左辺値になり、p+1は左辺値にならない。 p+1,p+2等は連続性のある領域確保(配列、calloc)の時だけ存在する。その並びを進んでいくから。 その歩幅は、(char **)*p領域を刺すのであれば、(char **)分だけ進む事となる。 このような理解で間違えていないでしょうか。アドバイスして頂けると有りがたいです。
age。
>>94 >char ***p;
>このように宣言した場合、
>&p番地に(char ***)型のp領域が生成される。
&p番地って? おかしな解釈はやめたほうがいいぞ。ちゃんと初心者用の入門書を買って読め。
あと、何も「生成」はされないぞ。
>>96 > &p番地って? 何も「生成」はされないぞ。
記憶領域が生成されるから、そこへアドレスを代入できるのでは,ないでしょうか?
p = malloc(char);
ポインタって、還元率は何パーセントですか。 20%くらい還元してくれたらうれしいな。 それとどこの店でもポインタは使えますか。 ゴールドポインタカードって誰でも作ることできますか。
× &p番地に(char ***)型のp領域が生成される。 ○ ある領域が(char***型の)pの為に割り当てられる ? しかし、&(p+1)番地に(char ***)型のp+1領域は生成されない。 あまりにも当たり前というか関係が無さ過ぎ。 まるで「今日ラーメンを食べても明日は晴れになるとは限らない」とでも書かれてるようだ。 わざわざこんな事を表明したり確認したりするのは勘違いの種が植えられている証拠。 ? p+1,p+2等は連続性のある領域確保(配列、calloc)の時だけ存在する。 もっとシンプルに考えるべき。ポインタがするのはあるオブジェクトを指し示す事だけ。 領域が確保されているかどうかは別の話。 ? その歩幅は、(char **)*p領域を刺すのであれば、(char **)分だけ進む事となる。 何が言いたいのかこの文章からだと正確に意味を汲み取れない。 コミュニケイションは大事なので表記法には気をつけましょう。 char***型の変数に+1するとsizeof(char**)の分だけ値が増えると言いたいのでしょうか?
>>99 res有難うございます。
p+1の確認について:
私の書きこみ
>>69 にて、p+1 を左辺値として誤用してしまい、
それに対して
>>71 等からアドバイスして貰いました。
そういう事が以前にあってp+1の事についての考えを書きました。
>> p+1,p+2等は連続性のある領域確保(配列、calloc)の時だけ存在する。 >もっとシンプルに考えるべき。ポインタがするのはあるオブジェクトを指し示す事だけ。 >領域が確保されているかどうかは別の話。 領域確保とポインタは別の話ですね。
>>99 > char***型の変数に+1するとsizeof(char**)の分だけ値が増えると言いたいのでしょうか?
その事が言いたかったのです。「(char **)*p」というのは、char**型の*pという事を示したかった
のです。キャストで書いておけば、変数名とその型の2つを表現できると思ったので。
このような表記法は、伝わりにくいですね。気を付けます。
int i, n[5]; for(i=0; i<sizeof n; i++) i[n] = 0; のようなコードを書いて新人を混乱させるのが僕の唯一の楽しみです。
>103 それで混乱させれるの?
ばぐるやん
頭のおかしい先輩と思われるだけのような・・・ ヒネルにしてももう少し知的なコードの方が。
107 :
デフォルトの名無しさん :03/11/30 22:48
>>103 i<sizof n
って、君配列を勉強しなおしなさい!
108 :
デフォルトの名無しさん :03/11/30 22:53
俺の環境だとsizeof nは20だ。
iが配列じゃなくてもできるの?
110 :
デフォルトの名無しさん :03/11/30 22:57
>>109 n[i]==*(n+i)==*(i+n)==i[n]
それ以前にかっこが無いだろ。
>>110 すごい、こんな使い方初めてしりました。感動です
この間その話題のときに初めて覚えて嬉しくてたまらないアホ発見。
>>111 sizeof は予約語だから()いらないよ
115 :
デフォルトの名無しさん :03/11/30 22:58
>>111 sizeofのことか?括弧が必要なのは型のサイズを知りたいとき。つーか型の時はキャスト式だから括弧が必要なだけ。
116 :
デフォルトの名無しさん :03/11/30 22:59
n[5]に値が入ってなくても良いのですか?
>>103 そりゃ混乱するわ。
i < sizeof n / sizeof n[0]
sizeof int == 1なんだろ
120 :
デフォルトの名無しさん :03/11/30 23:29
>>119 そう決まっているわけじゃないから、やっぱりダメ。
ぬるぽ
ガッ
123 :
デフォルトの名無しさん :03/11/30 23:35
sizeof nはいくつですか?
124 :
デフォルトの名無しさん :03/11/30 23:39
20
5
160
127 :
デフォルトの名無しさん :03/11/30 23:44
お前らほんとバカだろ?
ポインタのポインタのポインタのポインタ
void f(int n[]) { int i; for(i=0; i<sizeof n; i++) i[n] = 0; } のようなコードを書いて新人を混乱させるのが僕の唯一の楽しみです。
Oノ
ノ\_・’ヽO.←
>>128 └ _ノ ヽ
〉
131 :
デフォルトの名無しさん :03/12/01 00:31
ポインタのポインタのポインタをポインタにして そのポインタのポインタをポインタのポインタに ポインタのポインタのポインタとしてコピー
関数へのポインタの定義はなかなか覚えられん。
133 :
デフォルトの名無しさん :03/12/01 01:59
関数へのポインタの配列へのポインタってどうかくの?
134 :
デフォルトの名無しさん :03/12/01 02:25
こうやって
135 :
デフォルトの名無しさん :03/12/01 02:39
ばかはひっこんでてね
>>133 そのままじゃん
void (**pf)(void);
void(*p[])(void)
138 :
デフォルトの名無しさん :03/12/01 03:19
void(**p[])(void);
ポインターの何が難しいのか理解できない。
void(*(*p)[])(void);
142 :
デフォルトの名無しさん :03/12/01 03:34
int A; int*pA = &A; int**ppA = &pA; int***pppA = &ppA; int****ppppA = &pppA;
>>140 使い方をあまり知らないから「ね、ポインタって
難しいでしょ?」と言われると納得してしまいます。
ポインタだけが難しいという勘違いをするわけです。
未知の事なんて何でもかんでも難しいし、慣れない
テクニックを利用するのはややこしいものなんです。
だれか先人の中にポインタで極端に苦労した人がいたんでしょう。
"Cの"ポインタを根本から理解してない奴は、よく
>>146 なことを言う。
ポインタに限らないな 数学の数列が難しいというやつとかと似てる
int A; int &rA = A; int *pA = &A; int *&rpA = pA;
変な例かもしれないけど、自分は先にアセンブラ覚えたけど、 そのときポインタといえばインデックスレジスタを指すていう 前提でやってたから、C言語のポインタはなんか違和感があって すんなり使えなかったです。
んーーーー んーーーー んーーーー #include <stdio.h> int main(void){ int week; char *WeekName(int); for(week=0;week<7;week++){ printf("loop (%d) [%s] *WeekName:(%d)(%d), *WeekName(week):(%d)(%d) WeekName:(%d)(%d), WeekName(week):(%d)(%d)\n" ,week ,WeekName(week) ,sizeof(*WeekName),(unsigned int)*WeekName ,sizeof(*WeekName(week)),(unsigned int)*WeekName(week) ,sizeof((unsigned int)WeekName),(unsigned int)WeekName ,sizeof(WeekName(week)),(unsigned int)WeekName(week) ); } return 0; } char *WeekName(int nn) { static char *name[] = { "Sunday","Monday","Tuesday","Wednesday", "Thursday","Friday","Saturday" }; return((nn<0 || nn>6) ? name[0] : name[nn]); }
WeekName(week) で参照できるのは ポインタの指す、文字列のあるアドレス *WeekName(week) で参照できるのは、 ポインタの指す、文字列の先頭一文字のデータ printf関数の%s変換は最初からポインタを引数にするようになっているので アドレスを指すポインタを引数に与えると、 そのアドレスにある文字列が表示される。 他は、なんか値があるけど、関係ないので、この際気にしない。 unsigned intの値を表示するための printf関数の変換指定文字は%dでなくて%uでした。 たまたま負の値が出なかったので、警告されなかったようです。 ポインタ専用の%pというのもあるようです。 汚しまして失礼。 それでは、ばかは、ちょっとだけ出たので、寝ます。
printf("loop (%d) [%s] \ *WeekName:(%d)(%d), *WeekName(week):(%d)(%d) \ WeekName:(%d)(%d), WeekName(week):(%d)(%d)\n"
ポイソタって食べ物でつか
おまえらはどっち (1) int *a; (2) int* a;
おまえらはどっち (1) int *a, *b; (2) int* a, b;
おまえらはどっち (1)(´Д⊂ヽ (2)(つД`)
(; ・`д・´) !? (`・д´・ (`・д´・ ;)
>>156 関数の戻り値にポインタがあった場合は(2)、通常は(1)
int* CreateInt()
{
int *p = malloc (sizeof int);
return p;
}
といった感じ
int *を返す二つの関数のプロトタイプ宣言を並べたいときは? int* foo(void),* bar(void); 並べるやつがわるいのか?
一貫性の欠如
>>156 int*型のaを宣言しているのであって、int型の*aを宣言しているわけではないと言う
意味合いからは(2)。
>>157 間違いを起こさないためには(1)。
と言うのを天秤にかけ、ポリシーよりも安全性を選ぶ俺は(1)。
一貫しているとでもいってほしいのか?
int *a で混乱するのはCに不慣れな初心者だけだろ。
int* a,b; なんてやるのもね。
>int *a >で混乱するのはCに不慣れな初心者だけだろ。 で混乱するのはおかしくない? むしろ >int* a,b; >なんてやるのもね。 コレはかなり禁止だろう。 見た目悪すぎ
>>170 初心者にポインタを分かりにくくしている原因の一つかもね。
int* a;
しか許されてなかったら、初期化してないポインタに対していきなり代入
*a=0;
という誤解は減ったかも。
int* a という表記は考え方としては間違ってはいないが 実際にコードとして書くのは(文法的には正しいとしても)明らかに間違い。 なぜなら int* a, b が期待した挙動を示さないから。ゆえにどんな場合でも int *a と書くべき。ケースによって int* a int *a を使い分けるメリットは皆無。逆に表記の一貫性を損なうというデメリットしかない。 C言語はセンスの捻じ曲がった人間が開発した以上(素人の)常識は通用しない。郷に従うのが筋。 これに反論する奴は #define BEGIN { #define END } とかやってる奴と同類。
176 :
デフォルトの名無しさん :03/12/06 23:48
C言語のポインタに関して、アセンブラをやっとくと解かり易いって聞いたんですが、 もしかしてアセンブラ命令の LAD GR1,A とかそんな感じの事でしょうか? 確かにポインタと酷似してるんですが・・・
アセンブリ言語のどの命令、って訳ではないんじゃない? 大体いろんなアセンブリ言語あるし。 アドレスとかデータとか、間接アドレッシングだとかラベルだとか、 その辺使ってれば容易にポインタなど理解できると言う意味では?
179 :
デフォルトの名無しさん :03/12/07 00:10
あんまり説得力ないなぁ。 int *a という表記は考え方としては間違ってはいないが 実際にコードとして書くのは(文法的には正しいとしても)明らかに間違い。 なぜなら int *a, b が期待した挙動を示さないから。ゆえにどんな場合でも int *a もしくは int* a と書くべき。ケースによって int* a int *a を使い分けるメリットは皆無。逆に表記の一貫性を損なうというデメリットしかない。 C言語はセンスの捻じ曲がった人間が開発した以上(素人の)常識は通用しない。郷に従うのが筋。 これに反論する奴は #define BEGIN { #define END } とかやってる奴と同類。
>>180 がもう一回出してくるから良く読んでみたら
最後の方は理論が通ってるが前半は合わないや
int* a;
これは邪悪なのでやめたほうがいい
int* a, b;
*がどちらへかかってるのかわかりづらい
int *a, b;
とやって a がポインタである事を明示的に示すべき
int *a;
int b;
とやるべきでもあるかも知れない
182 :
デフォルトの名無しさん :03/12/07 01:37
Cの構文がもっとすっきりしていたら 初心者の混乱も少なくて済んだのにね
ちなみにvcで自動生成されるコードの多くは hoge* hoge;
>>181 いやー、論旨をひっくり返そうとしたけど失敗したんだよ。
気にしないで。
int* n; C++的。 int *p; Cプログラマーに多い。要するに古い。 int* p,n; コレの意味が同型だと理解するようなやつは一から勉強しなおせと言いなくなる で結論は最初はスタイルなど気にせずわかりやすい意味のある変数名、関数名などでプログラムを 組んでいくほうが後々のためだと思うのだが。エレガントなプログラムなんて後からついてくるもの。 と、俺は考える。
普通ポインタはtypedefすると思うが。 typedef int *pint; pint p,n;
>>181 氏の考えに続いて
ゆえに
int *a;
int* a;
どっちでもいい、と考えてみる 1変数宣言派はいないかなぁ。
そうする機会はありそうです。感謝。 なんで気付かなかったんだろ?
ブレインファックやれば?
>int *a; >int* a; > >どっちでもいい、と考えてみる 1変数宣言派はいないかなぁ。 なんでこだわるかというと、 >int* n; C++的。 >int *p; Cプログラマーに多い。要するに古い。 >int* p,n; コレの意味が同型だと理解するようなやつは一から勉強しなおせと言いなくなる 一番↓の通り、同じ型に”見える”。 わざわざ解りにくいように作る必要は無い。 言語によっては int* a, b; とやって intを指すポインタ a と intを指すポインタ b って同じように創られるものもある つまりCで言うところ [int* a b;] が [int *a, *b;]という意味になる でもCは違うので、変数ごとに解りやすくやったほうがいいわけ
>>int* n; C++的。 ハァ?
いいじゃんどっちでも。とっとと仕事しる。
結構くどいね。
195 :
デフォルトの名無しさん :03/12/07 13:28
ポインターに整数入れるの方が馬鹿。
>>194 妄想はいいから
>>int* n; C++的。
の根拠を示せ。
& じゃなくて * のな。
両方に対応できて区別できる能力が必要。 書き方に こだわりすぎると 他人のソースも ろくに読めなくなるんじゃね?
>>196 その根拠? C++的の言葉じたい抽象的、
その言葉を
>>196 がどう捉えているか知らんが
俺はC++でその表記が多いと感じたまで。
200 :
デフォルトの名無しさん :03/12/07 14:12
200
でも、キャストするときは(int*)だよな…
202 :
デフォルトの名無しさん :03/12/07 14:21
関数へのポインタについて教えてください。
質問を教えてください
割れずください
翼を下さい
206 :
デフォルトの名無しさん :03/12/07 14:46
>>174 そういや、そうだなぁ。
今度 C++で
int* a;
の表記をしようと思っていたがやめた方が吉なのか。
この板でそういう記述の人がいて、みてみると
なるほど、その方が合理的だよなぁと思ったんだが
int* a, b; で b がポインタにならないのであれば
誤解を与えやすいな。
207 :
デフォルトの名無しさん :03/12/07 14:50
ポインタは考え方よりも実際のコード(表記)で混乱することが多い。 K&Rにもよく理解できない複雑な事例が載っていたなぁ・・・ この辺を極める本ってあります? K&Rはちと説明が簡素すぎてよく理解できなかったんだ。
そんなに間違えやすいか? じゃあ int* p, n; とすりゃいい。
>>205 いま私の願いごとが かなうならば翼がほしい この背中に鳥のように 白い翼つけてください
この大空に翼をひろげ 飛んで行きたいよ 悲しみのない自由な空へ 翼はためかせ行きたい
いま富とか名誉ならば いらないけど翼がほしい 子どものとき夢みたこと 今も同じ夢に見ている
この大空に翼をひろげ 飛んで行きたいよ 悲しみのない自由な空へ 翼はためかせ
この大空に翼をひろげ 飛んで行きたいよ 悲しみのない自由な空へ 翼はためかせ 行きたい
>>206 いまだにそんなこといってるのか?
・1行に複数の変数を宣言/定義しない。
・変数を定義するときは可能なかぎり初期化する。
というのが、いまどき普通だろ。
>>210 俺はプロじゃないんで、よく分からんのですが
そういうもんですか。
ポインタと普通の変数を一緒に定義する時は int *p, n; 単独の場合はint* p;にしている 一貫性がないが、場合分けの基準は一貫しているので問題ない。
一緒に宣言する変数を増やしたくなったり、 減らしたくなったりしないのか?
それぞれが「俺が普通だ!」と言うスレ
int *p,n; だよ〜
216 :
デフォルトの名無しさん :03/12/07 17:39
俺はどうでもいい変数以外init a,b,c;見たいな書き方せんな。 int a; // コメント int b; // コメント 見たいな書き方が多い。i,j等のループに使うどうでもいい変数だけは 羅列することが多い。ポインタの場合、どうでもいいポインタって俺の使い 方ではほとんど無いから羅列したことは無い。 そんな俺は int* a; と宣言する派。
>>217 あぁ、専門学校だろ?
専門学校はコメントを良く書けといわれるらしいな
>>218 の言っている専門学校ではそういう風に習うんだ…
変数名がコメントを兼ねるように書けばいいだけ
>>219 うん、そうみたいね。
俺も通ってるわけじゃないから詳しい事は解らないけど
聞いた話によると就職にコメントが詳しく書いてあると有利らしい
ときどきは間違ったプログラム、つまり期待してた動作をしなくても入社できるらしい
うわ〜。うそ。変数名それぞれにコメントかいたってしょうがないべな。 そんなことしたら変数名の意味がなくなるし。
>>220 つまり
int comment_count;
char comment_str;
とかにするって事?
とボケてみたけどレベルいくつでしょう?
>>220 ってゆーか
int loopCounter_1_to_10_forUse_arrayTbl;
char *errorMessage_pointer_for_get_functionReturnStatus;
とかなら俺は嫌。
もっとも
int l; /* arrayTbl[]用に1から10の値で使うループカウンタ */
char *m; /* 関数を呼び出した際、エラーメッセージを受け取るポインタ */
とかだとさらに嫌
226 :
デフォルトの名無しさん :03/12/13 19:49
>>217 ループだけに使う変数は、柿のように使うのはどうでしょうか?
…
{int a; for(a…){
}}
…
int * const a; int* const a; int *const a; int*const a; どれが好み?
#define CPINT int*const CPINT a;
CPINT a, b;
>>229 それやったらやっぱbはポインタじゃなくなるんですか?
いいえ
>>231 いいえ。
typedefじゃないもん。
>int * const a こんなんはじめて見た。 ポインタの中身じゃなくて、ポインタそのものの値が固定になるのか?
短い範囲のforループ変数はiとかjとか使ってる 判定条件の変数にちゃんと名前が付いてれば何のループかすぐわかるじゃん。 ループ変数だと一目でわかんない名前の方がもっとイヤ
>>233 その通りだ。因みに
const int * a
int const * a;
この二つは、同じだ。
236 :
デフォルトの名無しさん :03/12/14 22:24
ポインタ難しいいいいいいいいいいいいいいいいいいいいいいl490わうmんふぉいさ@yfr987wqrfgth97wt3qlkじょkさfじヴぉあsAAAAAAAAAAAAAAA””””!!!!!!!「
237 :
デフォルトの名無しさん :03/12/15 14:14
役に立つか立たないかは置いといて、以下のようなこと出来る? #include <stdio.h> void main (void) { char a,b,c,null; a = 'a'; b = 'b'; c = 'c'; null = '\0'; int txt =a<<24 | b<<16 | c<<8 | d; char *str = (char *) txt; printf ("%s\n",str); } これで、abc と出力できる?
コンパイルエラー
#include <stdio.h> void main (void) { char a,b,c,null; int txt; char *str; a = 'a'; b = 'b'; c = 'c'; null = '\0'; txt = null<<24 | c<<16 | b<<8 | a; str = (char *)(&txt); printf("%s\n",str); } うちの環境だとこれでいけた。
240 :
デフォルトの名無しさん :03/12/15 14:47
ああ、そうだった。 char *str = (char *) txt; じゃなくて、 char *str = (char *) (&txt); か。 それと、 int txt =a<<24 | b<<16 | c<<8 | d; じゃなくて、 int txt =a<<24 | b<<16 | c<<8 | null; だった。 でも、できるのかなあ?
>>237 int が 32bit なら
int txt =a<<24 | b<<16 | c<<8 | d;
↓
int txt = ntoh(a<<24 | b<<16 | c<<8 | d);
で出来るだろう。
やっちまったよママン… × ntoh ○ ntohl
警告: 代入により、キャストなしで整数からポインタを作りました 警告: 代入により、キャストなしで整数からポインタを作りました 警告: 代入により、キャストなしで整数からポインタを作りました 警告: ポインタと整数との比較を行なっています 警告: ポインタと整数との比較を行なっています 警告: ポインタと整数との比較を行なっています ”警告”とは? 柔道のルールに反する様な危険な行為を故意に行った、 故意に場外に逃げる行為を行ったなどと審判が判断すると、 その程度により、注意、警告を宣告されます。あまりにひどい行為の場合は、 即「反則負け」となります。 *「警告」は「技あり」を1つ取られたのと同じ扱いになります。
そこそこうけた
245 :
デフォルトの名無しさん :03/12/16 03:37
ポインターが、あると何ができるようになるんですか? もしくは無いとできない事ってなんですか?
口座を用意しておくとお金を振り込んでもらえる 振込先が分からないので使えるお金がない。。。
247 :
デフォルトの名無しさん :03/12/16 05:03
>>246 int a; /*口座を作る*/
a=10; /*口座に振り込む*/
じゃダメなん?
これだと口座10に移動した、とかって事になるのか。
マジ質問なの? マジレスするなら、aに振り込んでくれという人と、bに振り込んでくれという 人がいるとき、振る込む人にどこに振り込むかおしえるのにポインタが使える。
ポインタの概念は理解できても表記方法がサッパリ覚えられん どうやって覚えたの?
考えてる暇に書きまくる
>>253 英語でポン。
C言語完全制覇より抜粋
int *ap[10]; ap is array of pointer to int.「apはポインターへの配列(要素10)です」
int (*pa)[10]; pa is pointer of array to int. 「paは配列(要素10)へのポインターです。」
int (*fnp)(double);
fnp is pointer to function(double) returning int.「fnpはintを返す関数(引数double)へのポインターです。
こんな感じで解釈するみたいです。
>C言語完全制覇より抜粋 C言語ポインター完全制覇の間違いね
257 :
デフォルトの名無しさん :03/12/20 13:04
定番 void (*signal(int, void (*func)(int)))(int); signal is a function(int,func is a pointer to function(int) returning void) returning a pointer to function(int) returning void ここで、a pointer to function(int) returning voidをtypedefするとわかりやすい typedef void (*HANDLER)(int); HANDLERを使うと、上記の英文は次のようになる signal is a function(int,func is HANDLER) returning HANDLER Cの構文で表すと HANDLER signal(int,HANDLER func); ここまで整理されるとやっと意味がわかる。
258 :
デフォルトの名無しさん :03/12/20 23:51
↓のhogeって、結局何なの? void *(*hoge[])(int)(char *);
259 :
デフォルトの名無しさん :03/12/20 23:53
訂正です。↓ void (*(*hoge[])(int))(char *);
hogeはポインタの配列・・・
>>255 その本最悪だな。俺なら
int* p; // p はintへのポインタです。
int* pArray[10]; // pArray はintへのポインタの(10個の要素を持つ)配列です。
微妙に外れるが配列の書法と関数ポインタの書法は失敗だったと
Cを作ったカーニハン博士自身も仰っている。
>>261 俺なら以下が何がいいたいのかわからない。
>>255 の本のは
* と [] と () と型名とを「結合順に」「英語で」 読んでいけば理解できるってことだろ?
>>259 hoge is an array of a pointer to a function (int) returning a pointer of a function (char *) returning void
int を受け取って、char へのポインタを受け取って void を返す関数へのポインタ、を返す関数
へのポインタの配列
>>257 たしかにtypedefははずせないね。
とくにc++でtemplate使った構文を作るときになんかないと不便ですね。
>>262 そうそう大事な事書き忘れてた。
>>263 日本語訳こちらの方がよくない
hogeは返り値無しの関数(引数char*)へのポインターを返す関数(int)へのポインターの配列
265 :
デフォルトの名無しさん :03/12/21 10:04
英語で解読するメリット
1.結合順位に従って読み下した順番に並べていけばいいこと。
(日本語だと、日本語の言葉の順番は逆なので、頭の中で並べ直さないといけない)
2.語順は結合順なので、何通りにもなることはない。
(日本語だと
>>263 >>264 のように、同じhogeを扱っているのに、いい訳と悪い訳ができることがある)
3.[]を見たらarray of〜、*を見たらpointer to〜、()を見たらfunction(〜)と言った具合に、機械的・反射的に探すことができる。
int* p; intへのポインタのp 先生!日本語で読めました!
>>266 だれも日本語で読めないなどは言ってないのですが。
なるほどなるほど…
dereferenceを逆参照とさえ読まなければ 英語だろうが日本語だろうがどっちでもいいよ。 ポインタが理解できないのは単に頭が悪いから。言語は関係ない。
>>269 というより語順をあわせたら
解かりやすくなるという物でもなさそう。。。
271 :
デフォルトの名無しさん :03/12/23 11:55
Cの構文は右左に飛ぶから、読みづらい
printf("\x1b[%d;%dH", y, x); 猫でもできる・・・であったプログラムなんですが どうやらエスケープシークエンスがだめなんです。 どうしたらよろしいのでしょうか? XP使っています。
NULLって結局なんなんですか? よくファイルオープンのあと if ( fp == NULL )とか if ( !fp )とか書いてあるんですが
○チはいらんのだよ
>>273 >NULLって結局なんなんですか?
ヌルポインタ
つまりNullPointerExceptionとは、 int *a=NULL; *a = 10; みたいなことをやると起きるの?
>>273 初期化されてないポインタの中には適当な値が入ってます。
だからポインタが何処も指していない状態を厳密に示す
ために値としてNULLを入れてやります。
例の「 if ( !fp ) 」が通用するのは、NULLは実際には
' 0 ' で定義されてたりする事が多いからみたいです。
あまり良くないのかも?それとも無問題?
・ポインタとかポインタへのポインタとか、とにかく戻り値がどこかのアド
レスな関数では、処理が失敗したときNULLを返すように作る事も多いです。
・特にどこも指し示していないポインタはヌルポインタとして初期化します。
こんな感じで良いでしょうか?>>ALL
>>277 無問題
例えヌルポがオール0ビットで表されていなくても
「(void *)0」がヌルポになることが保証されている
さらに「if( NULL )」が偽と判断されることも保証されている
気をつける点は「#define NULL (void *)0」を使う事と
ポインタを渡すべきところに0を渡したりしないという事
後は放っておいても大丈夫
280 :
デフォルトの名無しさん :03/12/24 10:43
NULLの定義が入っているのってstdlib.hでいいんだっけ? あと、どこにも向けてないポインタを使うと、 実行時エラーが出るけど、ゴミアドレスが、たまたまOSから見て、不正なアクセス領域を指してなければ、 エラーは出ないもんなの? つまりゴミアドレスの内容によって、エラーが出たり出なかったりするのかな?
>>280 >NULLの定義が入っているのってstdlib.hでいいんだっけ?
sidio.hやstring.hにも定義されている
>どこにも向けてないポインタを使うと、
どこにも向けてないポインタ=NULL
では?
2ちゃん語の「ぬるぽ」ってどういういみですか?
( ・∀・) | | ガッ
と ) | |
Y /ノ 人
/ ) < >__Λ∩
_/し' //. V`Д´)/
(_フ彡 / ←
>>282
>>281 初期化していない、って意味かと。
だとしたら、
>>280 >たまたまOSから見て、不正なアクセス領域を指してなければ
問題なくアクセス出来るでしょう。読み取りデータには意味が無いですが。
ただし、読み取りは可能でも書き込みは出来ない領域なんてのがある
場合があって、そのときは他のエラーが発生するでしょうね。
>>284 「NULLで初期化する」という言い方もあるから
「初期化していない」ではないと思う。
いったい何を説明して欲しいのだろう?
/* * char型6つぶん calloc したつもりなのですが、 * scanfすると何文字でも入ります。 * * この場合 6文字目以降は、 * はいることははいるけど、 * その後の運命は完全に無保証、ということでいいのでしょうか ? */ #include <stdio.h> #include <stdlib.h> int main(void){ char *str; printf("宣言直後:%p\n", str); /* gccだとこの時点でアドレスがある。*/ /* iccだと 空ポインタ */ printf("calloc後:%p\n", str = calloc(6,sizeof(char))); printf("5文字入力_" ); /* char型6個ぶん確保したつもりなのですが、 */ scanf("%s", str); /* 何文字でも入ります */ printf("%p %s\n", str, str); free(str); return(0); }
/* * とりあえずこんな感じで、希望の動作になりました。 * 惚け防止に最適 > Cげんご */ #include <stdio.h> #include <stdlib.h> int main(void){ char *str; printf("宣言直後:%p\n", str); printf("calloc後:%p\n", str = calloc(6,sizeof(char))); printf("5文字入力_ "); int i = 0; while(1){ if(((*(str + i) = getchar()) == '\n')){ *(str + i) = 0x00; break; } if(i == 5){ puts("5文字に切り詰めます"); *(str + i) = 0x00; break; } i++; } printf("入力後 :%p\n|%s|\n", str, str); free(str); return(0); }
291 :
デフォルトの名無しさん :03/12/25 20:42
>>285 >「NULLで初期化する」という言い方もある
のがわかっているなら、「初期化していない」ということになるだろう?
C言語というより日本語の理解の問題のような気もするが念のため
「初期化していない」
int *ptr;
「NULLで初期化する」
int *ptr=NULL;
>>291 「NULL 以外で初期化する」
int *ptr = (int *)0x1000;
「初期化したけどどこにも向いていないポインタは存在する」
みたいな事を
>>285 は言いたいんじゃないかと。
// でもそこで争う気はないんでスルーした次第。
おまいらNULLを指してるポインタと ダングリングポインタの違いもわからないのですか?
お前はダングリングポインタが何なのか誤解してる
295 :
デフォルトの名無しさん :03/12/26 09:18
ダングリングポインタって何ですか?
>>294 正式な定義がどうかは知らないけど (あるの?)、世間的には
1. 解放済みの領域を指すポインタ
2. (1. に加えて) 関数が戻した、そのローカル変数へのポインタ
3. とにかく何処を指しているか解らないポインタすべて
の 3種類あるよね。
俺の認識では 2. なんだけど。
case1: char *p = malloc(1024); free(p): // now p is a dangling pointer case2: char *p = malloc(1024); char *q = p; p = realloc(2048); // now q is a dangling pointer case3: char *p; void foo() { char q[1024]; p = q; // p is a valid pointer return; } void bar() { // p is an undefined pointer foo(); // now p is a dangling pointer }
>>298 >p = realloc(2048);
どこを再確保する気?
世間的にはどうか、ってのを置いとくと
実のところ 1. と 2. は区別する必要はないと
自分では思ってるんだけど。
そういや C++ だと、こういうのもあるね。
const char *ptr = std::string("ABC").c_str();
sprintf("%s\n", ptr); // pointed to temporary instance
>>297 で、そこは“普通”あるいは“正式な定義”なの?
# そもそも「正式」って誰が決めるんだろうね。
>>297 参照先の英文にはfreeともreallocとも書いていないのに、
freeやreallocに限定して、>296の2.を否定するのは作為的だな。
>>297 >>301 [Jargon File]とあったのでnew hacker's dictionaryを見てみたらあったから、そのまま乗せるぞ
dangling pointer [原義:宙ぶらりんのポインタ]
n. 実際にはどこにもたどり着かない参照(Cなど一部の言語では、実際には何にも有効
なものを指していないポインタ)。指していた相手が移動したり消えたりしたために起
こるのが普通。この語は技術的は意味を広げてハッカー語として使われており、たと
えば、もう国の反対側に引っ越してしまった人の市内電話番号は宙ぶらりんポインタ
だ。dead linkと比較せよ。
>>301 296の2は、単なるinvalid pointer
>>300 別に「正式」なんぞを決める必要は無く、みんながどう使ってるかが問題なのでは?
ググればわかるだろ。
305 :
デフォルトの名無しさん :03/12/27 13:51
>>289 いくらでも文字は入るけど、ヒープ領域をぶっ壊してるだけ
ポインタを宣言した時点では、どこも指していない。デタラメなアドレスが入っているだけで、有効なアドレスは指していない。
freeで解放した時点では、free解放直前までと同じアドレスが入っている。しかし、解放してしまえば、有効なアドレスを指しているとは言えない。
「ポインタを宣言したら、NULLを入れておく」、
「freeで解放したらNULLにしておく」、
といったように、これらのどこも指してないポインタを、プログラマが明示し、
このポインタを使用する関数に、ポインタがNULLのときは、エラーを返すようにする、
というのはよく使われる手段である。
>>305 たまたま有効なアドレスをさしているということはありえる。
>>272 あ、それね。
XPのcmd.exeは標準でANSI.SYSを読み込まないから、無理だよ。
漏れもconfig.NTにDEVICE文を付け加えてみたけど、どうも上手くいかない。
まあ、SetConsoleTextAttribute()を使いなさいってこった。
ポインタが無効になったらNULLを代入するのは良い手法だな。 エラーの発生ポイントをチェックできるし。
>>306 たまたま有効なアドレスをさしているということがありえるから、バグを見つけにくくなるわけで、
なら、最初っからNULLにしておけば必ずエラーになるからバグが見つけやすくなるというのが
>>305 の言いたいことでないの?
>>309 何が言いたいのかは知らんが、間違ったことを言ってるから指摘しただけだ。
>>310 間違ったことって…
そんな重箱の隅をつついて初心者に対して難解な文章にする必要は無いだろう
>>310 >何が言いたいのかは知らんが、間違ったことを言ってるから指摘しただけだ。
相手の言いたいことすら理解できていないのに、
発言する奴の方が技術者に向いていないと思うが?
因みに
>>309 の言いたかったことを代弁すると・・・
「お前の指摘(?)は的外れ。出直して来い」
pt = 0; if(!pt)
>>314 >>312 は俺じゃないんだが、それはおいとく。
314は312に向けた発言だと思うが、312がどれほど技術者に向いてなかろうが、
君の資質とは全く関係の無いことだ。もう少し冷静になって書き込めよ。
それに他人の代弁なんかする必要は無い。話がややこしくなるだけで、何の利益も無い。
それに、いやに305の肩を持つが、305が何かすばらしいことでも言ってるのか? Cプログラマであれば常識の範囲でしかないことだろう?
>>316 >それに他人の代弁なんかする必要は無い。話がややこしくなるだけで、何の利益も無い。
君、技術者に向いてないよ。止めたら?
>>317 常識を知らんやつに常識を教え込んでいるのは素晴らしい事だろう
常識知らんプログラマに囲まれて仕事はしたくないぞ
香ばしいスレになってまいりました
>>319 で、常識を知らん奴に教えるときには、その内容にうそが含まれていてもよいとでも?
香ばしいなw
323 :
デフォルトの名無しさん :03/12/29 06:09
関数・・・void func(int a[]) の引数にint型の配列s[]の先頭要素のアドレス・・・s(&s[0]) を渡せる理由が分かりません。 もちろんポインタ変数にアドレスを渡す方法なら余裕で理解できますが。こういうやつvoid func(int * a)
325 :
デフォルトの名無しさん :03/12/29 09:16
にゃあにゃあ
326 :
デフォルトの名無しさん :03/12/29 22:16
ポインタ理解不能
ポインタなんて分かっちゃえば簡単なのに なんでそんなに逃げ腰なんだ
ポインタ変数をポインタと略すな。 アドレスをポインタと呼ぶな。 そもそもポ゚インターの概念を廃止するべきだ。
ポインタ==最強
>ポ゚インター ??
>>328 同意。混乱の素だよな。ポインタって禁止用語にすればいい。
>>327 トラウマ糞コード書く香具師がいるから。
ポインタでつまづいてるようでは一流のプログラマーにはなれませんか?
どこにもつまずかなくても一流のプログラマにはなれませんが
↑嫌われ者はどっかいけよ
>>337 >>255 でおいらがしーぼん紹介してあげたんだな〜。
よって既出!!まあ。サイトまでは紹介してあげてなかったけどね。
/* * 笑い話に出てくる、ポインタのポインタのポインタの... * というのを実験してみた。 */ #include <stdio.h> #include <stdlib.h> int main(void) { char test[] = "oreore"; char **p = calloc(1, sizeof(char *)); char ***q = calloc(1, sizeof(char *)); char ****r = calloc(1, sizeof(char *)); char *****s = calloc(1, sizeof(char *)); *p = test; *q = p; *r = q; *s = r; printf("%s%s%s%s%s\n",test, *p, **q, ***r, ****s); printf("%p %p %p %p \n %c %c %c \n", test, p, q, r, *test, *(test + 1), *(test + 2)); printf("%p %p %p %p \n %c %c %c \n", ****s, ***s, **s, *s, *****s, *(****s + 1), *(****s + 2)); free(p); free(q); free(r); free(s); return (0); }
>>339 何の実験だか知らないが、
> *p = test; *q = p; *r = q; *s = r;
ぬるぽ。
ちなみに俺のメモリー確保はmallocだ
ちなみに俺のプログラムは #define malloc(n) calloc(1,n) をコメントアウトすると動かなくなるんだ
343 :
デフォルトの名無しさん :04/01/05 17:10
mov ax,word ptr ds:[dx]
>>343 16ビットモードだと dx による間接アドレッシングはできない。
bx, si, di のどれかにしろ。
345 :
デフォルトの名無しさん :04/01/07 22:49
∧_∧ ( ゚Д゚ ,,) { ギコ猫だってCやるんだぜ。 ) _ | ̄ ̄||_)_ / /|――||/旦/| | ̄| ̄ ̄ ̄ ̄ ̄| . | |三|_____|/ カタカタ・・・・
>>328 >アドレスをポインタと呼ぶな。
呼んでない。
恐らく、そう呼んでいるのは理解してないヤシだけ。
347 :
デフォルトの名無しさん :04/01/08 14:03
int* a,b; ってやったらaもbもポインタになるようにしてほしい。
今さらそんな機能が追加されても、邪魔なだけ。
邪魔って言うか過去のソースが全滅しそうだな。
お行儀の良すぎるソースなら大丈夫だよ。 int i,j,k; int *p,*q,*r; こんなことしてるのは少数派だろうが。。。
おれの場合typedef使うからな typedef int* inpee inpee a,b;
typedef foo* fooptrとか大嫌いで存在すら認められないってのがいるからなあ。。。
>>352 そういう人はCのみで終る人生でありC++にステップアップできない人だからほっときましょう。
>>352 あー、俺もそれは嫌だな。
いちいち定義する必要があるのかと一晩中(ry
お前 * 見たくないだけちゃうんか、と。
イタイ
>>355 お注射しますか?それともフェラチ●しますか?
357 :
デフォルトの名無しさん :04/01/10 14:04
教えてください goto *(void (*)())0x6000; と書いたときの動作と意味がわかりません。
アセンブラレベルでステップ実行してみなよ。
359 :
デフォルトの名無しさん :04/01/11 18:32
引き数なし、戻り値なしの関数へのポインタ型に0x6000をキャストし、 0x6000の指すアドレスにジャンプせよ。 0x6000にはジャンプしないと思う
360 :
デフォルトの名無しさん :04/01/11 18:45
>>1 ポインタは、アドレスを格納した変数のことだよ。
メモリに直接アクセスできるから、配列を使うより効率的なんだ。
>>360 > メモリに直接アクセスできるから、配列を使うより効率的なんだ。
こう信じ込んでいる奴って多いのか ?
>>359 0x6000にジャンプさせるには
goto (void (*)())0x6000;
じゃない?
手元にクロス環境がないのでわからないけど。
>>361 それはそれで正しいんじゃない?
int f(int *****ap, int n)
{
int a;
for(a=0;a<100;a++){
int ****bp=*(ap+n), b;
for(b=0;b<100;b++){
int ***cp=*(bp+n), c;
for(c=0;c<100;c++){
int **dp=*(cp+n), d;
for(d=0;d<100;d++){
n+=*(dp+n);
}
}
}
}
}
>>363 悪いけど、これを配列で表現してみてくれ。
(n+=*(dp+n); の型が不一致であることと、関数の戻り値が指定されていないことにはあえて触れないが。)
配列の方がポインタ読んで飛ばずに済むから早いのでは。
366 :
デフォルトの名無しさん :04/03/09 22:22
367 :
名無し@沢村 :04/03/09 23:09
>>360 >メモリに直接アクセスできるから、配列を使うより効率的なんだ。
ほう…配列は間接的にメモリにアクセスするのかい?
インデックス使うからレジスタ直じゃないってことでしょ int型のポインタ、配列がそれぞれあるとして、 ポインタの場合 mov eax, dword ptr[edx] ; ポインタ参照 lea edx dword ptr[edx+4] ;ポインタ自身をインクリメント 配列の場合 mov eax, dword ptr[edx+ecx*4] ; 配列参照 inc ecx ;配列インデックスをインクリメント 見ての通り、ポインタにすると使用レジスタを減らせる
それこそ意味わかんね。 添え字変数の参照コストは比較しながら ポインタ変数自体への参照コストは無視していいってのかね。 配列がスタック上なら mov eax, [ebp-12+ecx*4] で参照するが、staticな領域にあれば mov eax, [_array+ecx*4] となって、全然ポインタ参照 mov edx, [ebp-16] (ポインタ変数の参照) mov eax, [edx+ecx*4] または mov eax, [_array] mov eax, [eax+ecx*4] と使用レジスタ数は変わらない。 eaxではなくecxなりをカウンタとして使うとしても ポインタ変数がレジスタ変数になっているなら 配列:ebpベース ポインタ:ebx(等)ベース ・・・まったく同じ レジスタではなく、スタック上に取られるなら 配列:ebpベース ポインタ:edxなりにロードしてから再度参照 static領域 配列:直接参照 ポインタ:edxなりに(ry
参照回数の問題じゃなくて、ヘボコンパイラだと添字分の足し算を 毎回するので遅くなる程度だ。 まともなコンパイラにちゃんと最適化させたら、たいてい差がなくなる。
だからヘボコンパイラだとポインタ変数の値を毎回読み出すから遅くなるんだろ?
372 :
名無し@沢村 :04/03/10 20:26
>>368 mov eax, dword ptr[edx] ; の場合、66 67 8B 02となってModR/Mバイトしか使わないが、
mov eax, dword [edx+ecx*4] ;の場合、66 67 8B 04 8Aとなるから、SIBバイトも使うってことか?
>>372 出た!アセンブラの話になると元気になる機械語使い沢村。
俺がだいたい分かったこと 自作関数にはポインタは絶対に必要!
375 :
デフォルトの名無しさん :04/04/18 10:15
例えば >1 ってのがポインタだな >1 は1に書いてある内容を参照せよって意味だしな。
376 :
デフォルトの名無しさん :04/04/18 13:36
ポインタは女の子のアドレスを保存するもの
377 :
デフォルトの名無しさん :04/04/18 14:53
すいません初心者ですが1から376を読んでもさぱりわかりません もっとわかりやすくお願いします。 要はポインタ渡しとアドレス渡しは一緒? ポインタってのはそこの場所に この変数Aが常駐してますよ って事? ※だからそこの値を参照したり 値を変更したり出来る アドレス渡しも一緒?
おんなじだよ。
379 :
デフォルトの名無しさん :04/04/18 16:09
>>378 じゃあなぜ文言をわざわざ分けているのですか?
おにぎりとおむすびのようなもんだ
381 :
デフォルトの名無しさん :04/04/18 16:18
382 :
デフォルトの名無しさん :04/04/18 16:24
>>381 それって実態が(このレスでいう女の子?)
アドレス渡しってこってすかい?
そこを参照すればいつでも女の子がいますよ みたいな
グローバル変数のアドレス → 本妻 スタティック変数のアドレス → 愛人 ローカル変数のアドレス → 現地妻 アロケートした領域のアドレス → 売女
384 :
デフォルトの名無しさん :04/04/18 16:34
>>382 ここでいうアドレスはあくまでも電話番号
あかん余計意味不になってきた
386 :
デフォルトの名無しさん :04/04/18 16:38
>>383 アロケートしたらフリーしなさい
メンバ変数には電車で毎朝会う子か?
387 :
デフォルトの名無しさん :04/04/18 17:09
newするタイミングは?
ムラムラしたとき
389 :
デフォルトの名無しさん :04/04/18 17:15
>>387 一通りのエラーチェックのすんだ後
必要って時のギリギリのときにnewするのがよろし
390 :
デフォルトの名無しさん :04/04/18 17:30
NULLチェック?
実はおまいらもポインタの意味わかってないと見た
ぬるボインだ
393 :
デフォルトの名無しさん :04/04/18 21:05
ポインタのポインタのポインタ(3P)
ポインタへのポインタへのポインタ
395 :
デフォルトの名無しさん :04/04/19 00:54
ポインタというか 間接アドレッシングがまともに装備されてないCPUがあることを初めて知った。 びっくらこいた。
396 :
デフォルトの名無しさん :04/04/19 01:59
>>1 アドレスをかくのうしているはいれつのメモリのことですっ!!!!!11
>はいれつのメモリ _| ̄|○
398 :
デフォルトの名無しさん :04/04/19 02:39
メモリを指し示すものがポインタだ。それ以外の解釈なんてありえない。
ウルトラ警備隊の専用車がポインタだ。それ以外の解釈なんてありえない。
オブジェクト相当のものを指し示すもののことだろ。 それがアドレスで実装されてるとは限らない。なんかのindexかもしれない。 メモリとも限らないかもしれない。
猟犬として改良されたものがポインターだ。愛玩犬としての解釈もあるかもしれない。
マウスで動かす画面上の矢印がポインタだ。それ以外の解釈なんてありえない。
403 :
デフォルトの名無しさん :04/04/19 11:56
>>400 はぁ?お前全く計算機のハードウェアがわかってないな。
オブジェクトはメモリ上にマッピングされなけりゃどこに
実装されるか考えてみろ。アホが
しかもindexとは何を意味してるんだ?それが物理的にどこに格納
されるか考えてみろ。
最後にスレタイよく読め。C++とは一言も書いてないだろうがバカ
>>400 C++で拡大解釈されたレジスタ変数へのポインタをありがたがってる
文法バカ -> ハードウェアのかけらも知らない糞
ポインタはあれだ 本のしおり
ポインタがなかったら世界のソフトウェア産業はここまで発展しなかった
>>404 お前はレジスタウィンドウや Mapped I/O すら知らないらしいな。
ぽいんたぁ
おおきなオッパイがボインだ。おとうちゃんの為にあるんと違うんやで。
>>407 チッ!あのなぁ。レジスタウィンドウなどというのはレジスタをメモリ
代わりに使おうって発想なんだからメモリといっても差し支えないだろうが!
しかもMapped I/Dの前には Memoryの修飾詞がつくだろうが、少なくとも
コンパイラ側から見ればメモリと思ってアクセスしてる。だから
Memory Mapped I/Oなんだよ。
>>409 pure Cではレジスタへのポインタは許されてなかったという経緯も知らんのか?
アフォが!
ポインタが何か理解できたが、実際使うこと少ないな。
>>412 そんなことはない。
int x[100];
int i;
for(i = 0; i < 100; i++ ){
x[i] = i;
}
と書くより,
int *px;
px = x;
for( i = 100; i > 0; --i){
*px++ = i;
}
という風にポインタのインクリメント/デクリメントに持ち込むほうが一般的に
速い。
415 :
デフォルトの名無しさん :04/04/19 14:37
質問はageよな
>>411 で、C++ は何の関係があるんですか?
>>403 >しかもindexとは何を意味してるんだ?
例えば、非バイトマシンにおけるバイト位置とかじゃない?
>>418 それは間違い。学生はスッコンデロ!コンパイルしてコード見ろ。
さらにカウントは0を終了条件にするほうが速いがこちらはどんな
オプティマイザでも一応対応してる。
レジスタの少ないCPUでレジスタ変数を指定することは逆に速度低下につながりかねないが ポインタのインクリメントやデクリメントはCPUにハードウェアとして実装されてる機能であって、 これを下手にアドレッシング計算されると速度低下につながる。 まぁ、日英/英日翻訳がまともに機能するようになればコンパイラに頼り切ってもいいだろうけどね。 今の自動翻訳で意味わかるか?
421 :
デフォルトの名無しさん :04/04/19 15:14
ちょっと難しいかな
422 :
デフォルトの名無しさん :04/04/19 15:25
>>420 レジスタって何CPUって何変数って何インクリメントって何デクリメントって何
ハードウェアって何実装って何アドレッシング計算って何コンパイラって何?
>>420 >ポインタのインクリメントやデクリメントはCPUにハードウェアとして実装されてる機能であって
絶対だな?
PICにはないよ。てか、間接アドレッシング機能がそもそもない。 メモリもなくてデータ/プログラムともレジスタだけで動く。
>>419 お前は実際にコーディングして確かめたのか?
頼むから知識だけで物事を語るのはやめてくれよな。
ちなみに漏れの環境での結果は、(1000万回ループ)
>>413 の上: 7937(ms)
>>413 の下: 8078(ms)
まぁ大差はないがそういうこった。
漏れの環境がおかしいとか言われそうだなw
まぁ別にいいけど( ´ー`)y━〜~~
まあ
>>413 みたいな細かい気配りが出来る人って
俺ゴリズムを駆使した挙句、猛烈に遅いコード書いたりするよね。
>>413 程度のことを細かい気配りとか思っちゃってる香具師がいたのか。絶句。
あ、プログラマじゃないよね。じゃ仕方ないか。
>>413 のプログラムは上と下で違うことをしてる
正しくは、
void funcA(){
int x[100];
int i;
for(i = 0; i < 100; i++ ){
x[i] = i;
}
}
void funcB()
{
int x[100];
int *px;
px = x+99;
for( int i =99; i>=0; --i){
*px-- = i;
}
}
(´-`).。oO(なんで皮肉が通じないんだろ?)
gcc -O2 -march=pentium4 の結果は funcA は .align 2 .globl __Z5funcAv .def__Z5funcAv;.scl2;.type32;.endef __Z5funcAv: pushl%ebp xorl%eax, %eax movl%esp, %ebp subl$408, %esp L6: movl%eax, -408(%ebp,%eax,4) addl$1, %eax cmpl$99, %eax jleL6 leave ret
funcBは .align 2 .globl __Z5funcBv .def__Z5funcBv;.scl2;.type32;.endef __Z5funcBv: pushl%ebp movl$99, %eax movl%esp, %ebp subl$408, %esp leal-12(%ebp), %edx L14: movl%eax, (%edx) subl$4, %edx subl$1, %eax jnsL14 leave ret ループ部分ではクロック数には差がないがループに入る前で1命令分だけ funcAが少ないな。
>>425 お前いったいコンパイラに何使った?
次のプログラムで確認してみろ!
#include <iostream>
#define N 10000000
int x[N];
void funcA(){
int i;
for(i = 0; i < N; i++ ){
x[i] = i;
}
}
void funcB()
{
int i, *px;
px = x+N-1;
for( i =N-1; i>=0; --i){
*px-- = i;
}
}
int main()
{
funcA();
funcB();
}
gcc 3.3.1 コンパイラオプション -O2, gprof の結果は index % time self children called name <spontaneous> [1] 100.0 0.00 0.09 main [1] 0.06 0.00 1/1 funcA() [2] 0.03 0.00 1/1 funcB() [3] ----------------------------------------------- 0.06 0.00 1/1 main [1] [2] 66.7 0.06 0.00 1 funcA() [2] ----------------------------------------------- 0.03 0.00 1/1 main [1] [3] 33.3 0.03 0.00 1 funcB() [3] ----------------------------------------------- 0.00 0.00 1/2 _GLOBAL__I_x [28] 0.00 0.00 1/2 _GLOBAL__D_x [25] [6] 0.0 0.00 0.00 2 __static_initialization_and_destruction_0(int, int) [6] ----------------------------------------------- つまりfuncAの方がfuncBより倍遅い。これでも上が速いというか?
この程度のプログラムで時間で計測しても誤差ばかりが目立つぞ。
>>433 ==
>>419 か?だとしたら学生じゃないんだな?
…恥の上塗りだな。
そんなもの、コンパイラにもプロセッサにも依存する。
>>425 コンパイラの話をしてるのにコンパイラにもプロセサにも依存するのは当然だろうが。
86系でクロック数をカウントできるデバッガでも持ってりゃそれで示してやるがあいにく
持ち合わせてないんでな。
それともタイマ等もすべて止められるOSでポート叩いてロジアナでモニタすれば計測できるが
お前はそれやったのかい?
439 :
デフォルトの名無しさん :04/04/19 19:24
440 :
デフォルトの名無しさん :04/04/19 19:24
gprofをつけると一部の最適化ができなくなったり 余計な命令が含まれてしまったりするのではないだろうか。
メモリは国土 グローバル変数は世界遺産 ローカル変数は時価の高い土地 アロケート領域は借地
444 :
デフォルトの名無しさん :04/04/19 22:09
今更の今更だけど、その程度のコードでは速度差なんてほとんどでないから、 理論的に計算して時間を求めたほうがいいよ。 たとえば1MIPSのコンピュータでどうとか。 速度はある程度遅い方が顕著になるともう
アメリカのブッシュちゃんに「さーフセインちゃんをやっつけましょ〜」 って言われてイラクくんだりまで尻尾ふってついてく小泉ワンワンのことさー。
>>437 本っ当に頭悪いね…
>>432 のコードは、前者が速いこともあれば後者が速いこともある。
ふつーは後者が速い、なんてのは幻想。
>>446 お前アセンブリコードをまともに書いたことのない最低のド素人だな。
C書く前にCPUの構造を一から勉強しなおせ。
>>447 は昨日入門書を見ながら摂氏⇔華氏変換プログラムを書いて感動しました。
ハ ー ド ウ ェ ア の か け ら も 知 ら な い 知 障 に ア セ ン ブ ラ は 無 理
必死だなw
>>447 アセンブリは死ぬほど書きました。
モノが ROM なのでハンドアセンブルも多かったですが。
趣味では CPU も TTL ランダムロジックで幾つか作りましたよ。
尤もそのマシンはパイプラインや先読みキャッシュ、分岐予測なんてのは
備えてませんので、あなたの思うような結果 (後者が速い) に
なるでしょうね。
>>446 >ふつーは後者が速い、なんてのは幻想。
それはお前のおつむが幻想見てるからだよ。配列のアドレッシングに出来るだけポインタの
インクリメント/デクリメントでアクセスできるようにデータをあらかじめ並べ替えて配置
するなどというのは常套手段。ループカウンタでお手軽にアクセスするのは
人間にはわかりやすくても機械にとっては負担が大きい。
私は
>>446 の意見に一票。
コンパイラによっても処理系によっても結果は違う、が厳密には正解だと思う。
だが、現実的にはこの程度のコードで差を生じさせるようなアホなコンパイラも
貧弱な処理系も稀な気がする。(組み込み系とかを除けば)
あとついでに言っとくと、アセンブラがどうのこうのとか (私に言わせると素っ頓狂なこと)言ってる人は、頭の中に昔の8ビットの CPUとか想定してないか?
>>454 手元にLinuxかFreeBSDのソースコードあったら見てみな。カーネルだけでなく
ライブラリでもアセンブラで書かれてるものが結構あるから。Cのコード見てアセンブリ
結果を予測できないようじゃままごとアプリ書くのが関の山
>>455 数万行のCのコードを脳内アセンブルできないとダメですか。
(´-`).。oO(
>>432 で差が出るって言ってる人はx86しか知らないのかな)
68系、H8、あとほとんどのDSPでは明らかに差がでるな。むしろX86の方が差は出ない。
SPARC ではgcc -O3 で同じコード吐いた。
どうしても納得しない莫迦がいるようなので VC++ 6.0 & Win2000 with PenIII 866MHz で実測。 さて、どうなるでしょう!? (A) 意外と FuncA が速いんじゃない? (B) FuncB が速いに決まってる! DWORD s[2]; s[0] = GetTickCount(); funcA(); s[0] = GetTickCount() - s[0]; s[1] = GetTickCount(); funcB(); s[1] = GetTickCount() - s[1]; std::cout << "#" << i + 1 << ": " << s[i] << " [msec]" << std::endl; std::cout << "#" << i + 1 << ": " << s[i] << " [msec]" << std::endl; #1: 351 [msec] #2: 250 [msec] 次に、FuncA と FuncB の呼び出し順を入れ替えると #1: 360 [msec] #2: 251 [msec] というわけで正解は、「(C) 最初に呼び出された関数が遅い」でした。
同じコードは吐かんだろ?方やインクリメント方やデクリメント それを同じコードはいちゃオプティマイズしすぎだと思うが?
あれ、間違えた。コードの最後の2行は for (int i=0; i<2; i++) std::cout << "#" << i + 1 << ": " << s[i] << " [msec]" << std::endl; ね。
>>462 たしかに完全に同じではないけど
# Cソースコード
int x[1024];
void funcA(void) { int i; for (i = 0; i < 1024; i++) x[i] = i; }
void funcB(void) { int i, *p; p = x + 1023; for (i = 1023; i >= 0; i--) *p-- = i
; }
int main(void) { funcA(); funcB(); return 0; }
# 以下、アセンブリ
funcA:
sethi %hi(x), %g2
or %g2, %lo(x), %g2
add %g2, 4092, %g2
mov 1023, %g3
.LL6:
st %g3, [%g2]
addcc %g3, -1, %g3
bpos .LL6
add %g2, -4, %g2
retl
funcB:
sethi %hi(x+4092), %g2
or %g2, %lo(x+4092), %g2
mov 1023, %g3
.LL12:
st %g3, [%g2]
addcc %g3, -1, %g3
bpos .LL12
add %g2, -4, %g2
retl
ループ部分は同じでしょ?
このコードの内容はどちらも内容的にfuncBにコンパイルされてるね。 カウンタは、はじめに1023がセットされて addcc %g3, -1, %g3 でデクリメント。 ポインタも sethi %hi(x+4092), %g2 で配列の末尾がレジスタg2に設定されて、 add %g2, -4, %g2 で4byteずつデクリメント。 ループ途中でiを引数にした関数でもコールすると違ってくるんだろな
funcAでは一度配列の先頭がg2にセットしてからわざわざ4092足して 末尾設定してることだけが違う。
467 :
デフォルトの名無しさん :04/04/20 18:27
413のポインタの使い方おかしくね?あれじゃ遅いよ。
>>468 >413のポインタの使い方おかしくね?
どうおかしいの?
>>469 forのループでiのかわりにpxのポインタを使っていないとこ。
あーでもインクリメントしたiを入れたいのか。例が悪いな。
皿仕上げてるからマヌけなことかいてるのかと思えば、当たり前のこと書いてるだけジャン
2chには仕事でコンパイラ作ってる人もよく来るから、 生半可な知識を振り回すと恥をかくことが多い。
いい加減、自分が一番バカなことに気づけよ ->
>>473
「far ポインタ」って何?
いわゆるx86系CPUの話だが。 16bitCPU時代は、アドレスも16bitで表現していた。最大アドレス値は高々64Kbyte。 しかしメモリがメガ単位まで増えると、64Kbyteを超えるアドレスにアクセスする必要 が出てきてしまった。 そこで、アドレスを上位と下位の二つに分割して、64Kbyte以内のメモリ単位(この範 囲をセグメントという)のプログラミングでは通常の16bitポインタを使い、セグメントを 越えるメモリ操作は、上記の上位アドレスを併用することで実現した。 このような拡張アドレスを操作するポインタを farポインタとよび、これに対して従来 の物をnearポインタと呼ぶ。 またfarポインタの上位アドレスは、セグメントの基点をあらわすことからセグメントア ドレス、下位アドレスはセグメントを基点としたオフセット表現なので、オフセットアド レスと呼ぶこともある。 現在ではCPUが32bitになり、アドレスバスも32bitに増えた。このため表現できるア ドレス空間も4Gまで増えたため、farポインタを使う必要性はほとんどなくなっている。
478 :
デフォルトの名無しさん :04/05/11 22:33
ポインタがないと困る点を5個述べよ。
479 :
デフォルトの名無しさん :04/05/11 22:54
モジュールの使い回しができない。
480 :
デフォルトの名無しさん :04/05/11 22:55
ポインタを使ったソースコードがコンパイルできなくなる。
char**と*chat[]って何が違うのよ?
リスト構造の実装が困難 ツリー構造の実装が困難 スタックの実装が困難 キューの実装が困難 …
>>483 全て参照を使うことでもっと簡単に安全に実装できますね。
ポインタのポインタはポポインタ
>>432 の実行結果ですが・・・
LccWinだと、こうなりました。
(W2K+sp4 P3-650*2)
Wedit profiler.
Command: "e:\lcc\hello.exe "
Generated 2004.5.12.1.49.26
_funcA | 123| 0| 55.16 hello.obj
_funcB | 100| 0| 44.84 hello.obj
_main | 0| 223| 0.00 hello.obj
Total profiler stops: 239
Total direct module hits: 223
Wedit profiler.
Command: "e:\lcc\hello.exe "
Generated 2004.5.12.1.54.25
_funcB | 122| 0| 55.71 hello.obj
_funcA | 97| 0| 44.29 hello.obj
_main | 0| 219| 0.00 hello.obj
Total profiler stops: 236
Total direct module hits: 219
やっぱり、先に呼ばれたほうが遅いですね?
488 :
デフォルトの名無しさん :04/05/12 04:13
test
>>484 >>483 の例はすべてクラスのメンバに他(or 自分)のクラスのポインタを含む場合だが。参照でどうやって書くの?
>>484 gccのbits/list.tccではポインタ使って書いてる。
ポポイのポポイのポポイのポイ ポポインタ
知ってるとプログラムが書きやすくなる。
493 :
デフォルトの名無しさん :04/05/12 19:23
p-
494 :
名無し@沢村 :04/05/12 19:47
>>1 本に書いてあるよ、本読めよ。
幼稚園かおまえ?
ポインタン
496 :
デフォルトの名無しさん :04/05/12 21:18
>>455 それはハードを操作するからじゃないのかね。
ブートローダとか、HDDの操作とか。
スピードのためにアセンブリ使っているわけでないような気がするが。
497 :
デフォルトの名無しさん :04/05/12 21:29
ってか413のプログラムって、Windowsで実行するのと、Linuxで実行するのでは、 計測結果が激しく違う予感がするぞぉ。 プロセスの管理方法とかが一緒なの毛? やるならブートローダーにそのプログラムを直に書いて、FDDでブートさせて計測したほうがよさそうな予感。 ってかそこまでやっても何も得られん・・・ゲハ
498 :
デフォルトの名無しさん :04/05/12 23:24
ポポインタのポポインタはタンポポ
499 :
デフォルトの名無しさん :04/05/12 23:35
ウィンドウズアプリなんかじゃ、スタック使うときだけポインタを使えばいいのか。 あとは参照にすべしで決まりだ。
>>496 strcpy() とかのソース見れ。
いくつかのプロセサは、文字列操作に特化した命令を持ってるから、そういうのを使うためにアセンブラで書くのは珍しくない。
>あとは参照にすべしで決まりだ。 参照なんてなもんはなくても構わない。
宣言時、初期化できない/したくないときは参照はつかえない。
504 :
デフォルトの名無しさん :04/05/21 00:18
age
505 :
佐々木洋子 :04/07/13 18:45
インポと名前が似ていて、聞いていて恥ずかしいですね(笑
>>495 >>498 上級者に、初心者はポインタの意味だけでつまずいてるわけじゃないことを
理解させることは容易じゃないようだ
メモリっていうのはビット列とそのビット列が入っているところをあらわす アドレスがあります。 たとえば、下の図がわかりやすいと思います。 左側にあるのがアドレスで囲ってあるところが中に入っているビット列が 意味する数字です。 +---+ 100 |10 | +---+ 101 |10 | +---+ 102 | 0 | +---+ 103 | 9 | +---+ |20 | +---+ int *a, *b; *a = 10; b=a; aはアドレスをあらわし、*aは中には言っているビット列をあらわします。 たとえば、メモリが上の図の通りになっているとすると、 aに100が入っていると、*aは10(この場合はint型だから数字だけど) をあらわすことになります。 ポインタとはメモリのアドレスを指し示すそのままの意味の「ポインタ」 なのです。メモリ上のビット列をアドレスでポイントしているのです。 では、b=aは何を意味しているのかというと、bにaのアドレスをコピー しているのです。 つまり、bには100が入って、aと同じ10という数字を示すことになります。
>>503 出来るだけそういう風に書かないでもいいようにコーディングしたい
メモリの事を丁寧に説明してからポインタに移るのが良し
自分が昔ポインタ理解できたきっかけは どこのアドレス指してるとかの説明よりも ディレクトリでかも知れんなぁ
511 :
デフォルトの名無しさん :04/11/20 06:47:56
**************** 糸冬 了 ****************
513 :
デフォルトの名無しさん :04/11/22 10:37:18
>>514 上手な説明をどうぞ。逃げないでちゃんと解説よろ。
516 :
デフォルトの名無しさん :04/12/01 21:07:53
中途半端にハードウェアの初歩的知識がある人には 「ポインタ」の箇所を「アドレス変数」って読み替えるといいよ、って言ってる。
517 :
デフォルトの名無しさん :04/12/01 21:19:24
int* a なら 「int型のアドレスを指す変数」 で 大体理解できるんじゃないか?
518 :
デフォルトの名無しさん :04/12/01 21:20:44
ファイルから文字列を読み込もうとしているのですが、 txtなら1行づつ読み取れるのですがexcelの場合は、そうもいかないみたいでして excelの場合の読み取りの仕方を教えてください。 以下に僕が作ったサンプルプログラムを書きます。 br = new BufferedReader ( new InputStreamReader ( new FileInputStream( "SJISin1.txt" ), "SJIS" ) ); while( ( str = br.readLine() ) != null ) { System.out.println( str ); } というような感じです。宜しくお願いします。 なお部分的に抽出する場合も教えていただけるとうれしいです。 例えば3行2列目の文字列を読み取るなどです。
csvじゃなくてxlsを読もうとしてる?
つーかマルチ臭がする上にスレ違い
521 :
デフォルトの名無しさん :04/12/02 18:50:52
元々過疎スレなんだし、スレのネタすら無くて終わってるんだから、 まったりと教えてやれよ。
522 :
デフォルトの名無しさん :05/01/07 15:15:54
2
523 :
デフォルトの名無しさん :05/01/07 15:16:17
22
上げてしもた…申し訳ないorz
ぽいんとあああああああああ
526 :
デフォルトの名無しさん :05/02/15 04:18:17
C言語のポインタは「指し示すもの」です。
マウスカーソルのポインタも「指し示すもの」です。
マウスカーソルのポインタて…orz
char *aに配列へのポインタを格納した場合配列の長さはわからない?
int main() { int a = 1000; int *p; int **pp; p = &a; pp = &p; printf("%d\n",**pp); return 0; } この場合、 a … 1000 p … aのアドレスを指す &p … pのアドレスを指す *p … pが指しているアドレスの値、1000を指す pp … pのアドレスを指す(つまり&p) *pp … pが指しているアドレスを指す(つまりp) **pp … pが指しているアドレスの値、1000を指す という解釈で合ってますでしょうか。
531 :
デフォルトの名無しさん :2005/04/28(木) 13:33:39
>>530 「ポインタ値=アドレス値」とは限らない。
「ポインタ値=オブジェクトを指し示す値」だ。
環境によってはアドレス値であるかもしれないし、
オフセットアドレスであるかもしれない。
533 :
デフォルトの名無しさん :2005/04/29(金) 08:29:58
関数名もポインタ?
「アドレスを指す」んじゃなくて「オブジェクトを指す」or「アドレス値を持つ」
あーわかんね もうポインタの本を何冊買ったか覚えてねえ タンスとかの図を載せてるけど コンピュータの中にタンスが入るわけねえだろとか 余計なことばっかり気になってしまう これはもう、能力とかじゃなくて相性だな
俺が初めてBASIC触ったときの説明書で(カシオのPB100)、 変数とか配列とかを箱が並んでる絵で説明してて、わけわからんかったな それはともかく、Cのポインタは便利すぎるのか、素人が苦し紛れに 使って、わかりづらいコードになること多い。配列使え
実はCでもJavaみたいにポインタを使わずに済む コーディング方法ってあるんだろ? 実行ファイルのパフォーマンスは最高なんだから あとはポインタさえなけりゃ最強の言語なんだよ なっ教えてくれよ
>>535 クロヌ
「ポインタの本」なんつーターゲット絞り込みすぎ気味の本なんてあるのか?
結構たくさんあるよ
>>538 ポインタ使わなきゃ関数にヒキ渡せないものばっかりジャン
そうなんだクロテゴメソ
難しいとは知ってたが見事にポインタでつまずいた。 いま「ポインタが理解できない理由」読んでるけど、 こんなんを初めてでも簡単に理解できる人は凄いよ。 Cの勉強し始めて「頭良い・悪い」が何なのか分かった気がする。
>>543 そういう本もある意味変だよな。
わからない理由がわかってたら
それはわかってるということだからな。
545 :
デフォルトの名無しさん :2005/04/29(金) 20:58:16
なんか自分で考える代わりに本を読むだけの人増えてる?
546 :
デフォルトの名無しさん :2005/04/29(金) 23:18:24
ハード的なメモリの構造について勉強したことがない?機械語で遊んだことがない?
547 :
デフォルトの名無しさん :2005/04/30(土) 08:50:54
win環境なら、VBとJavaとかから入るだろうから メモリ構造理解するとかしないでしょ
メモリ構造なんていうたいそうなもんでもないけどな。知るべきことは。 DOSのころは、セグメントだのバンクだのっていう瑣末なことまで気にしていたが、 今となっちゃただ単にリニアなアドレスを持つ仮想のメモリ空間を相手にするだけだ。 だから、そこじゃないんだろ難しいのは。 例のポインタに関するCの変てな表記法や文化が混乱の元。 関数ポインタとか、配列とポインタの混同とかさ。 ポインタ変数の、組み込み型変数としての普遍性と特殊性を押さえないとな。
メモリのアドレスを入れる変数=ポインタだと思ってるのだが違うのか?
550 :
デフォルトの名無しさん :2005/04/30(土) 10:22:40
まぁ、そんなところだ
551 :
デフォルトの名無しさん :2005/04/30(土) 10:31:04
で、分かんないのが関数ポインターってドウ使うの? Win32SDKで使ってたようなきがするんだけど、いまいち実感が無くて。 誰かおしえぇて。
>>551 関数を変数に入れたいときに使う。
変数に入れられれば、関数の引数として渡せるようにもなる。
配列にして番号で関数指定できるとか
>>551 REGISTERCLASSEX、CreateWindow、CreateDialog
単純な例ですが #include <stdio.h> typedef void(*FUNCPTRDEF)(int index); void FuncNPE(int index) { printf("ぬるぽ%d\n",index); } void FuncGa(int index) { printf("ガッ%d\n",index); } void FuncCall(FUNCPTRDEF func) { int i; for(i=0;i<10;++i){ func(i); } } int main() { FuncCall(FuncNPE); FuncCall(FuncGa); return 0; }
さりげなくぬるぽってるのが最高
Λ_Λ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ (・∀・ )< HSPで大金持ちになるんだ。 _φ___⊂)__ \_______________ /旦/三/ /| | ̄ ̄ ̄ ̄ ̄| | | |/
558 :
デフォルトの名無しさん :2005/04/30(土) 12:50:11
&と*が分かりにくい? しかしそういわれてモナー size ofみたいにaddress of演算子とかその逆のcontent of演算子とかにする? 長々しくなってヤダー
#define ADDRESSOF(v) (&(v))
文字列定数はポインタである、ってことがどうしても解りません。 教えてください。
>>560 ヒント:文字列定数が格納されているところのポインタ
voidへのポインタの配列へのポインタを引数にしてvoidへのポインタを返す関数へのポインタの配列を定義したい
さようなら
564 :
デフォルトの名無しさん :2005/04/30(土) 21:44:38
ボンジュ〜ル
typedef void *(*FUNC[])(void *(*)[]);
567 :
デフォルトの名無しさん :2005/04/30(土) 22:04:41
typedef void *PVOID; typedef PVOID APVOID[]; typedef PVOID FUNC(APVOID *); typedef FUNC *PFUNC; typedef PFUNC APFUNC[];
C言語って基地外だな。 *(*)[] ってばかじゃねーの?
570 :
デフォルトの名無しさん :2005/04/30(土) 22:15:50
上の方で紹介されてる「ポインタの本」ってこういう問題ばっかりガンガン載ってるのかな?
こんな問題は数をこなすより、個々の要素をちゃんと押さえるほうが大事。 ・関数ポインタ と その配列。 ・配列へのポインタ ・引数と返り値では、仮引数名が省略される。 この3つを押さえれば、どんな複雑な型でも書ける。
そもそもtypedefを使えばどんな複雑な型でも書ける。
char* szA = "1234568790"; char szB[] = "1234568790"; これの違いを適切に言えるなら初心者脱出。
実用レベルでは、「配列へのポインタ」ってほとんど使われない。 配列先頭要素へのポインタで事足りる。
>>575 2次元配列へのポインタをしまうときに使う。
int aa[2][2], a[2];
int (*pa)[2];
pa = &a
pa = aa;
ポインタって必要なの? アドレス参照したいなら&でいいんじゃないの?
>>577 なくても、プログラミング出来なくはない。
でもめんどくさいよ。
>>573 > char* szA = "1234568790";
char型のデータを格納するメモリのアドレスを格納するための
変数「szA」を定義し、文字列データ"1234568790"の格納されている
メモリの先頭アドレスを格納する。
> char szB[] = "1234568790";
char型の配列変数「szB」を定義し、文字列データ"1234568790"を
構成する各文字コードデータをszB[0]から順に格納する。
…これで合ってますかね
>>577 intのポインタとか便利じゃね?
アドレスだと、インクリするときにa=a+sizeof(int); とか面倒じゃね?
ポインタならa++;で済むからテララクスwwwwwうぇwww
>>577 おまいは全ての関数を値渡しで作るのか?
ポインタだって値渡しだ。 例えポインタがなくても、アドレスをintかlongにキャストして渡せば、同じことが出来る。 手間はかかるが。
環境によってはintで死ねる
なんか本末転倒なような アドレスを扱うんならポインタがあった方がいいでしょ アセンブラじゃないんだし抽象化もされてるし アドレスを扱わない言語仕様ならポインタも不用だけど 配列も関数も渡すのが難しくなる
?
別に阿呆じゃあないと思うよ 視点を変えて説明しようとしたんだろう 詰めが甘かったけど
ポインタ値をスカラ型にキャストするほど危険な事もないね。
んなこたない
ポインタを使わなければ、実現できないプログラムってあるんですか?
>>591 int main(int argc, char** argv)
Cに限ればいくらでも出てきそうだな
>>592 では、具体的にどういう時に使えば便利(に、プログラムが組める)でしょうか?
>>594 添え字無しで配列が扱えるところ。
えーと、たとえば
forで回してるときは愛があるから配列で・・・
whileで回しているときは愛がないからポインタで・・・
>>592 俺はこの「char **argv」でCに挫折した。
これは初心者に対するイジメだ。
>>595 なるほど、そうですか
あんまり、whileを使ったことがなかったですので
新鮮です。
while + ポインタ を研究してみたいと思います。 ありがとうございました
HSPからCに移行した時にポインタやアドレスを知って 今まで疑問だった部分があっさり氷解した覚えがあるなぁ あれは感動ものだった… 今ではポインタ無しとか不自由でしょうがない
600 :
デフォルトの名無しさん :2005/05/04(水) 19:25:45
char * が文字列だってことさえ理解したら char ** 問題ないでしょ?
問題なく理解できる人も居れば拒否反応見せる人もいるんだなぁ世の中には
602 :
デフォルトの名無しさん :2005/05/04(水) 20:42:20
typedef char * LPCHAR; typedef char ** LPLPCHAR; と定義すれば分かりやすい。
むしろ typedef char* PCHAR typedef PCHAR* PPCHAR
604 :
デフォルトの名無しさん :2005/05/04(水) 20:48:13
あ、そうね。
605 :
デフォルトの名無しさん :2005/05/04(水) 21:33:28
typedef char * String; のがいいんじゃない?
名前は好きにすればいい
どっちみちいつかはchar *を明かさなければならないときがくる。
>>600 char *が文字列のアドレスを持つ変数の宣言ということはわかる。
しかしchar **が何を意味するのかいくら考えてもわからない。
文字列のアドレスを持つ変数のアドレスを持つ変数宣言?
そうやっているうちにウッキーとなって本を投げて布団かぶって寝る。
言語で理解すんなよ。
関数の仮引数ならとりあえずchar *argv[]と書いて「ポインタの配列」と話を進められるが……。
>608 ま、こういうのは例を考えるのが一番 func1(){ char** array_str={ "ぬるぽ", "ガッ" }; func2(array_str); } func2(char** strings){ printf(*strings); //ぬるぽと表示 *strings++; //次の文字列に変更 printf(*strings); //ガッと表示 } とすると func2では、 *stringsでは、呼び出し元の文字列配列の書く文字列を指す。 **stringsでは、各文字をさす
>>611 例示ありがとう。
でも、んーわからん。
*が二つ以上付くとどういう機能を果たすのか
この根本原理がわからない。
文字列のアドレスを二つ別々に持てる変数…?
*stringsが各文字列を指して
**stringsが各文字を指す…???まるで魔法だ。
やっぱり自分には無理と思う。スレ汚しすまん。
それではさらばっ
図を書けばすぐわかると思うんだが。
>どういう機能 機能とか考えてる時点でだめだなw ** でポインタのポインタ "〜のポインタ"ってだけ
文字列って普通に使うものなのんだけど、Cで直接表現できないのが 初心者の混乱の原因なんだろうね。あと、ポインタと配列を意図的に混合してるのが 紛らわしいのかも。 ・Cの文字列の実体は char の配列なんだけど、 簡単に先頭要素のアドレスで表すことが多い (char *) これが重要 ・文字列の配列は、char ary[10][20] とか2次元配列で表現してもいいんだけど 普通は、実体はどっかに作っておいて、先頭要素アドレスの配列であらわす(char *ary[10]) で、main の引数みたいに、「文字列の配列」を他の関数に渡すときの、 呼ばれる側の関数の仮引数は、この場合 char *ary[10] または char **ary となる
思ったんだけど、ポインタの 『 * 』 が 『 演算子 』 だと気付いていない人が結構居そうな気がする あと、配列の 『 [] 』 も (ry
変数宣言(仮引数)のときは「演算」してないから、それを言っても・・
だからC++では「char*」で一つの型として記述しようとしてるんかの
大人しくStringにすればいいのに。
>>611 char *array_str[]じゃないと駄目だろ。
621 :
デフォルトの名無しさん :2005/05/05(木) 21:36:47
Stringを使え
おとなしくC++使えばいいのに。
char c; // c は char型 char *p; // *p は char型 char **pp; // **p は char型 char f(); // f() は char型 簡単だろ。
プ
プインタ
やったことはないけど、 char a; char ***b=&(&(&a)); みたいな書き方で良いの?なんかキモチワルイ。
>>627 そうはできない。
char c;
char *pc = &c;
char **ppc = &pc;
char ***pppc = &ppc;
typedef char SZ[4];
SZ sz;
SZ *psz = &sz;
SZ **ppsz = &sz
上のコード片をtypedefを使わないで書くと下のようになる。
char sz2[4];
char (*psz2)[4] = &sz2;
char (**ppsz2)[4] = &psz2;
そして配列から先頭要素を指すポインタへの読み替えでこんなことができる。
char *p2 = sz
char *p3 = sz2;
SZ hoge[8];
SZ *phoge = hoge;
char hoge2[8][4];
char (*psz3)[4] = hoge2;
こんなんだから混乱するんだよな。
629 :
デフォルトの名無しさん :2005/05/06(金) 19:35:37
&a = &b; とかは?
630 :
デフォルトの名無しさん :2005/05/06(金) 20:46:58
>>26 この連休にようやく仕様変更が行われますた。
しかしポインタで宣言した変数には既に前に値が入っていた模様
非処女 = クズ デカチチ = ゴミ チャパツ = カス 短スカート = アホ
>>629 &演算子の結果は左辺値ではないので = の左辺には置けない。エラーになる。
ただし大穴としてC++でaが何らかの(非constな)参照型を返すoperaotr &()をオーバーロードしているオブジェクトで、
&bの結果がその何らかの型へ変換できる場合はもちろんコンパイルは通る。
633 :
デフォルトの名無しさん :2005/05/06(金) 23:14:08
&a = &b; と同じことができる言語もあるのにね
>>629 &a = &b;
なんて真顔で書いてる奴見つけたら、キーボードで殴る
635 :
デフォルトの名無しさん :2005/05/07(土) 14:26:46
建設作業員の俺から言ってみれば おまえら何しゃべってるのか意味がわからん たのしいけえ?
建設作業員の僕でも楽しいです。
みなさん、最高ですか?
全てはいい加減な言語設計をした作者が悪い。 C作ったの誰だゴルァ
char a; char **b; char *A=&a,*B=*b;
>>638 文句あるなら自分で言語作れ。D言語みたいなのは無しの方向で
K&R読んで、C言語のポインターの仕様がスッと頭に入らなかった 敗残者のスレはここかよ、おぃ(獏称
642 :
デフォルトの名無しさん :2005/05/07(土) 16:51:19
*がアドレス **がアドレスのアドレス
ぬるぽを呼び出す方法。 ((void (*)())0)();
644 :
デフォルトの名無しさん :2005/05/07(土) 16:53:45
24 名前: ウンコ [sage] 投稿日: 2005/05/07(土) 13:51:53 /** Sample.c * コンパイル方法: * gcc -E Sample.c | sed -e 's!&\*!!g' > Sample.i.c * ~~~~~~~~~~~~~~~~~外部プリプロセス処理 * gcc -o Sample.exe Sample.i.c */ #include <stdio.h> #define S(v) &v // 下記置換はC pre processorでは不可能なので、外部プリプロセスで処理する //#define &* int main(int argc, char*argv[], char*envp) { int v = 1; // intの変数宣言 int *P; // intへのポインタ変数宣言 P = &v; // intのポインタ変数へ、intの変数のアドレスを代入 #define p *P //S(p); // intの変数へのポインタ //p; // intの値 int n = 2; // intの変数宣言 //n; // intの値 //S(n); // intの変数へのポインタ S(p) = S(n); // intのポインタ変数に、intの変数のアドレスを代入 // 外部プリプロセス処理の結果、 // &*P = &n は P = &n と同じ p = n ; // intの値の代入 // *P = n つまり v = n と同じ return 0; }
>>642 アドレスのアドレスってのが
どういう意味なのかさっぱりわからん。
ちょうど三次元の世界に住む俺らが
四次元の世界をイメージするようなもんか。
メモリのアドレスはアドレス一つで一意に決まるんだから
ポインタは*一つの使用法以外にないと思うのだが。
関数の中で引数で渡されたポインタの中身を変えたい時はどうすんのさ *aで受けてa = bとかしても変わらんから **aで受けて*a = bとかするだろー そんな複雑なもんじゃないよ
>>645 『アドレスを格納する変数』 のアドレス
>645 なんか、混乱してるようだけど そんなに難しいもんじゃないよ。 普通のポインタは int *p int i p=&i なら ポインタ変数(p) → ポインタにさされる変数(i) っていう風にさしてるよね? int **q int *p int i p=&p q=&p なら q → p → i っていう風にポインタがさしてるだけ。 ただ単に、→が1つ伸びただけ。
649 :
デフォルトの名無しさん :2005/05/07(土) 20:51:09
そこで、UMLのcollaboration図、Lispのセル図が、大活躍するですよ!!!
>>645 そもそも642の説明が間違っている。
変数宣言時はこんな意味になる。
* ポインタ変数。(変数のアドレスを格納する変数)
** ポインタへのポインタ変数。(ポインタ変数のアドレスを格納する変数)
どっちも変数のアドレスを格納すると言う点においては何ら変わりない。
652 :
デフォルトの名無しさん :2005/05/07(土) 22:54:04
機械語知ってれば間接参照なんてフツーに理解だけどね
16進数の羅列をみて何を理解汁と?
>機械語 正確にいうと機械語ではなくアセンブラだろ?
int *p; てのは p がintポインタ型という宣言じゃなくて *p が int型という宣言だろ。 C++ とかでよくやる int* p; て宣言は激しくキモいんだが。
だからポインタ型という型概念を作ってるんだろ、C++は
>>655 自身がキモイ
>>654 >ら?
アセンブラ
アセンブリ
アセンブル
アセンブレ
アセンブロ
アセンブリ茶
そりゃセンブリ
660 :
658 :2005/05/07(土) 23:45:53
ナ ゝ ナ ゝ / 十_" ー;=‐ |! |! cト cト /^、_ノ | 、.__ つ (.__  ̄ ̄ ̄ ̄ ・ ・ ,. -─- 、._ ,. -─v─- 、._ _ ,. ‐'´ `‐、 __, ‐'´ ヽ, ‐''´~ `´ ̄`‐、 / ヽ、_/)ノ ≦ ヽ‐'´ `‐、 / / ̄~`'''‐- 、.._ ノ ≦ ≦ ヽ i. /  ̄l 7 1 イ/l/|ヘ ヽヘ ≦ , ,ヘ 、 i ,!ヘ. / ‐- 、._ u |/ l |/ ! ! | ヾ ヾ ヽ_、l イ/l/|/ヽlヘト、 │ . |〃、!ミ: -─ゝ、 __ .l レ二ヽ、 、__∠´_ |/ | ! | | ヾ ヾヘト、 l !_ヒ; L(.:)_ `ー'"〈:)_,` / riヽ_(:)_i '_(:)_/ ! ‐;-、 、__,._-─‐ヽ. ,.-'、 /`゙i u ´ ヽ ! !{ ,! ` ( } ' (:)〉 ´(.:)`i |//ニ ! _/:::::::! ,,..ゝ! ゙! ヽ ' .゙! 7  ̄ | トy'/ _,,. -‐ヘ::::::::::::::ヽ、 r'´~`''‐、 / !、 ‐=ニ⊃ /! `ヽ" u ;-‐i´ ! \::::::::::::::ヽ `ー─ ' / ヽ ‐- / ヽ ` ̄二) /ヽト、 i、 \:::::::::::::::..、 ~" / ヽ.___,./ //ヽ、 ー
あっセンブリ茶なのね
あっ、センズリ中
>>663 わしの部屋に監視カメラ付けたのはお主じゃな
666 :
デフォルトの名無しさん :2005/05/08(日) 03:03:32
667 :
デフォルトの名無しさん :2005/05/08(日) 05:40:19
>>655 セマンティクスではそうなるけど
キャストなんかでも変数の型としては
int *
とするんだから
>>1 規格では
・オブジェクト(と関数)を指し示すための値
・ポインタ型として宣言されたオブジェクト
・宣言子中の識別子の前の * と型修飾子の並び
K&Rでは他の変数のアドレスを内容とする"変数"
>>667 セマンティクスでもそうはならない。
宣言子中の * は演算子じゃないし。
てかみんな何で規格書読まないの?
規格書って何?
670 :
デフォルトの名無しさん :2005/05/08(日) 08:44:03
セマンティクスでそうじゃないの? int a, *b, c[10], *d(); なんてできるじゃない?
>>670 見た目が同じってだけ。
*bと同じ見た目の式はint型だけど*bという宣言子はint型でも何でもない。
constを入れてみたら、別のものだってわかると思う。
int * const b;
という宣言は書けるけど、
* const b
なんて式は書けないよね?
675 :
デフォルトの名無しさん :2005/05/10(火) 06:26:05
>>672 言っていることがよく分からないのだけど
宣言子をどう解釈するかはコンパイラの仕事であって
それはシンタックスの問題だと思う
人間は「*bがintになるようなポインタ変数なんだな」と
理解して読んでるんじゃないの?
だからaも*bも**cもカンマで区切って並列に記述するのに躊躇しないんだと思うんだけど
676 :
デフォルトの名無しさん :2005/05/10(火) 06:54:57
677 :
デフォルトの名無しさん :2005/05/10(火) 07:15:10
678 :
デフォルトの名無しさん :2005/05/10(火) 07:51:04
うわぁ〜
>>675 「人間がどう理解するか」なんて話をいつどこで誰がしたんだ?
規格書の意味規則には「*bがintになるようなポインタ変数」に類することは一切書かれていない
だからセマンティクスでも
>>655 が言ってることは間違い
655みたいな解釈がしたけりゃ勝手にすればいいが、嘘は書くな
int *p とか int* p とか言ってるけど、int * p の3単語で認識するヤツは以内のかしらん
関数の戻り値と仮引数はそう書いてる。 void * f(const char * s) てな感じ。
int a=4; int* b; b = &a; int c; c = *(int*)(unsigned*)(double*)(char*)(long*)b; if (a==c) puts("別になんともないよ"); こういうのって普通は動作するものなの? まあ使うこともないんだけど
>>683 ポインタは、昔のfarなどを除いて、基本的には
どんな型でも、サイズ(sizeof(type*))が同じ
で、型によって、アドレスが変わるって事はないので、問題ない。ハズ
685 :
デフォルトの名無しさん :2005/05/12(木) 08:30:02
セマンティクスって人間の理解している意味ってことだからだよ
>>684 int a=4;
int* b;
b = &a;
int c;
c = *(double*)b;
if ((double)a==c) puts("別になんともないよ");
だったら?
語源の話なんか誰もしとりゃせんがな
>>686 は、↓がポインタの代入に見えるらしい・・・
c = *(double*)b;
>>685 こりゃまたトンデモ解釈だな。そんな訳初めて聞いたよ。
Cの作者は、
>>675 が言うように
>人間は「*bがintになるようなポインタ変数なんだな」と
読ませたかったのかもしれないが、その目論見はどう見ても失敗してて、
こうして混乱してスレ立てたりする奴が出てくるわけだ。
上のような解釈は、既出のようにconstで破綻するし、見ようによっては
関数ポインタでも配列でも破綻する。また、関数の仮引数や、
文字配列の初期化などの例外について、この解釈は何も語ってくれない。
675の言うような解釈を勧めている入門書もあるけど(望洋本とか)
混乱を招くだけだと思うよ。
690 :
デフォルトの名無しさん :2005/05/12(木) 21:48:38
constで破綻するというのは int * const bの宣言はできるが* const bという式はダメという例? int const bは宣言できるけどconst bという式はないんじゃないの?
691 :
デフォルトの名無しさん :2005/05/12(木) 21:51:02
>>688 ポインタの代入じゃないんだけど・・・
ポインタのキャストで指されている変数の型のサイズが広がったらって例です
一部間違い
int a=4;
int* b;
b = &a;
double c;
c = *(double*)b;
if ((double)a==c) puts("別になんともないよ");
ね
692 :
デフォルトの名無しさん :2005/05/12(木) 21:55:54
あと、セマンティクスは文字通り「意味」ということ 僕はこれを「人間の解釈」のつもりで使ってきたけど そうではない用語として使う人もいるってことだね そのことは理解できました
>>683 元と同じポインタ型へ戻せば値不変が保証されるらしいから問題ないだろう。
694 :
698 :2005/05/12(木) 23:28:42
>>690 >int const bは宣言できるけどconst bという式はないんじゃないの?
だから破綻するって言ってるんじゃん。いったい何が言いたいの?
そういや、C++の&でも破綻するよな。
>>692 「意味」とは「人間の解釈」のことである、と認識してる奴は珍しいと思うが。
普通こういう文脈でセマンティクスと言えば、文法よりもうワンランク上のレベルの
「意味論」という意味で、
「それ、文法的にはあってるが意味がないぞ」とか言う場合の「意味」という
言葉に近い意味だと思う。
代入した時の型と、実際に使う時の型が同じであれば、問題ない それが異なる場合は、使い方次第 int *a; double b; char c=1; *(a=(void*)&b)=0; *((char*)a)=c; if(*((char*)&b)==c)puts("別になんともないよ"); if(*a==(int)c)puts("環境次第")else puts("この使い方は駄目よ"); あまり、良い例じゃないけどね…
>代入した時の型と、実際に使う時の型が同じであれば、問題ない たとえばchar*とint*でポインタのサイズが違うような処理系もあったと思うが。 そういう処理系だと、char*からint*にキャストした時点で情報が失われるんじゃ ないかな。
>>694 うーん、それじゃ、ポインタ変数の宣言でconstをそこに入れるのと
ポインタ変数を使う場合にconstを入れられないのを例示された意味が分からない
僕が追加したのはポインタ変数でなくても宣言にはconstを入れられるし
変数を使う時には入れられないのだからポインタの宣言についてのみ破綻していると
指摘されるいわれはないということなんだけど
*bがintという意味で
int *b
としてもbを定数と宣言するならbにconstがついて
int * const b
になるのは当然に思うよ
>>696 聞いた事ないけど、そんな環境があれば、駄目だね
ただ、その場合、
char *cp ;
int *ip ;
cp = malloc ( sizeof(*cp) ) ; /* cpとipでサイズが違うのに */
ip = malloc ( sizeof(*ip) ) ; /* どうやって代入してるの? */
等の処理が特殊であると思われる(ANSI等に準拠してない?)ので、
あまり気にする必要もないかもしれないが…
そんなものは無い near far は昔あったがなー
64bit環境だとやっぱりポインタも64bitになるんですか?
>>700 よう分からんけど、それってANSI等の規格に準拠してるの?
まぁ、準拠しているのであれば、
>>698 の動的確保が上手く行くはずで
内部的にポインタを自動変換する機構を持っているはずなので、
>>695 のように、
>代入した時の型と、実際に使う時の型が同じであれば、問題ない
と思うけどね…
>>701 環境次第でしょ
>>702 準拠してるよ。規格では、異なるオブジェクト型へのポインタのキャストを
認めていて、「与えられた境界調整をもつオブジェクトへのポインタは、
同じか、より制限の弱い境界調整をもつオブジェクトへのポインタに
型変換して、再び元に戻してもよいことを保証する」というところまでは
書いてあるが、境界調整の強い方へキャストして戻ることまでは保証してない。
で、動的確保に関して言えば、あらゆるオブジェクト型へのポインタは
void*にキャストすることとvoid*からキャストすることは認められているから
問題ない。
でも、たとえばchar*をint*にキャストしたら、元には戻らないかも知れない。
>>703 なるほど
char*やvoid*の方が他のポインタと比べて細かく指定できる
(byteポインタやwordポインタがある)環境では
他のポインタにキャストすると切捨てられる可能性があるって事ね
705 :
694 :2005/05/14(土) 13:44:57
>>697 >ポインタ変数を使う場合にconstを入れられないのを例示された意味が分からない
しらんよそんなもん。
>>672 を書いたのは俺じゃないし。
俺が言ってるのは、プログラミング言語の宣言を読むのに、コンパイラの解釈と
違う解釈をしてもメリットはないだろう、ということ。
オブジェクト指向の説明をするのに犬猫ほ乳類を持ち出すようなもの。
まあ、初心者向けのウソを含む解釈が、初心者の助けになるなら
それを使うのもひとつの手だが、少なくともこの例では混乱を招いている
だけじゃないかと。
int array[10];
int *a = array;
みたいなのを見て混乱した、って話がこのスレの上の方でなかったっけ。
確認しないで書いてるけど。
まだやっとったんか。
constは「破綻する」例として出した訳ではないんだがな。
破綻する例だとしても一つありゃ十分だろ。
それから、
>>675 >宣言子をどう解釈するかはコンパイラの仕事であって
>それはシンタックスの問題だと思う
コンパイラが何をするものなのか理解してないのか。
単に用語を間違ってるだけか?
宣言子をどう解釈するかはセマンティクスの問題だ。
シンタックスの問題は「それが宣言子であるかどうか」だ。
707 :
デフォルトの名無しさん :2005/05/15(日) 10:16:20
ポインタで渡した方が、値がコピーされない分高速になるのでしょうか?
>>706 ポインタでも普通の変数でも同じ状況であるなら
「破綻する」としていることが何か分からないけど
ポインタの宣言においてconstを入れることで破綻することって何なの?
宣言死をどう解釈させたいかはコンパイラの設計者の考えているセマンティクスであって
コンパイラはシンタックスに従って形式的に変換していくだけ
コンパイラの設計者の考えているセマンティクスはコンパイラの動作のためのもので
コンパイラを使うプログラマが考えているセマンティクスとは若干違うね
>>707 ポインタ渡せば実際の値はコピーされないが、ポインタの値がコピーされますが何か?
int a = 5;
int b = a;
int *p = &a;
これで下の方が早いと思うならまだまだだな
>>705 まあ確かに
int *a=array;
の例で初心者は混乱するかもしれないね
けどaの宣言をしているんだから初期値の代入をするのはあくまでa
それは宣言以外の式の中で左辺値として使う場合とは違うと認識しなくちゃいけない
int a[3]={1,2,3};
でも定義されているのはあくまでaでしょ?宣言以外の式の中じゃa[3]にこう代入することはできないわけで
>>709 もっとでかい構造を持った変数とかのことじゃない?そういうのを渡せる言語もあるから
>>711 ていうかCだって構造体を関数の引数として渡すことできるよな。
だから、ある程度わかっている人同士の会話なら、
「ポインタで渡した方が、値がコピーされない分高速になる」
という言い方で通じるだろうけど、こういうのが現場で「伝承」されていくうちに、
intまでポインタで渡す奴が出てくるというのはありそうな話なわけで… w
いくらできるからって構造体を直接値渡しするヤツなんて居るのか?
>>712 >だから、ある程度わかっている人同士の会話なら、
考えるまでもなく、ポインタの方が高速な訳で…
どちらかと言えば、教えた人の言葉の一部分だけを捉えて
勘違いする奴がいるだけではないかと…
>>713 Win32APIなんかはPOINT(メンバはintが2つ)くらいだと値渡ししている。
そんなことしてるAPIあったのか・・・ GetWindowRectとか、受け取るのに構造体使ってるのしか使ったこと無いから知らねぇな・・・
>>713 64bitの値でlong longを使いたくない(使えない)場合は構造体を使って値渡しやね
オセロの先読みルーチン作るとき、再帰的に先読みするんだけど、 各手を売った後の盤面の構造体(enum 8×8の配列含む)を値渡ししてたな。 もちろんこれは必要性があってやったわけだけど。
>>718 うむ。その場合は盤面をまるっと渡したほうが楽だな。
>>710 同意だが誰がどういう主張をしているのかもう少しちゃんと読め、と。
あと、
>>708 はもう放っといてやれ
おまいら、構造体の値渡しの時、calloc()でメモリ領域取得しないんですか? #include <stdlib.h> #define B_SIZE 8 typedef enum { empty=0, white=1, black=2 } CellState; typedef struct { CellState at[B_SIZE][B_SIZE]; } Board; void bar(Borard b) { for (int i=0; i<B_SIZE) for (int j=0l j<B_SIZE) b.at[i][j] = empty; } // 引数で渡された構造体ポインターの中身は、書き換えたくない void foo(const Board *b_ptr) { // calloc()で構造体を、ローカル変数領域(スタック上)にぴーこ Board *b_copy = (Board *)calloc(1, sizeof(Board)); memcpy(b_copy, b_ptr, sizeof(Board)); // ぴーこした構造体を渡す bar(b_copy); // リターン時、b_copyに確保した領域は自動的に開放される }
> // リターン時、b_copyに確保した領域は自動的に開放される されねーよ ていうかそのまま渡せや
おまえそれ超おかしいから
725 :
723 :2005/05/16(月) 21:03:32
Board *b_copy宣言なのに
bar(b_copy)でいけるしそれで値渡しだと思ってる
>>721 に蝶ワロス
あ? 関数宣言は void bar(Board b); だから、 呼び出し側も Board *b_ptr; bar(*b);って補完してねっ☆おねぇさんのお願い やっぱvoid *calloc(size_t)知らなかっただろ? この情報は為になりましたか? (●とても役に立った ○大変役に立った)
× Board *b_ptr; bar(*b); ◎ Board *b_ptr; bar(*b_ptr);
>>722 calloc()が確保したメモリは、
ローカル変数と同じ、スタック上に確保されるんで、
ローカル変数同様、関数を飛び出た直後に解放される
>>
>>730 calloc
要素を 0 に初期化した状態で、メモリ内に配列を割り当てます。
alloca
スタックにメモリを確保します。
きゃん!
ワロス
くぅーん
ちなみにサイズがあらかじめわかっているものにallocaを使うのはただのバカ。 ただのローカル変数の方がずっと良い。
そゆこと。 さっき書きかけたんだけど、おねぇさんに逆らうスカポンタンが居たから廃棄した
昔、デフォルト4kスタックのころにalloca使われてえらいめにあった 今は平気なんだろうけど抵抗あるな・・・
>>737 今でもデフォルトのスタックはそんなに多くないぞ。
デフォルト1MBじゃなかったっけ
740 :
喜屋武 :2005/05/18(水) 15:10:09
可変長配列を宣言できないコンパイラが多すぎる
俺はC89に対応していれば十分。
できないときは、とりあえず[1]で
return _alloca(sizeof(NULLPO));
age
746 :
デフォルトの名無しさん :2005/06/29(水) 10:48:44
ポインタのポインタのことで質問なのですが、どういうときに使われるのでしょうか? ポインタ配列のポインターとして使うのは、わかったのですが他にどう使うのかがわかりません。 たとえば、二分探索木で使われているのですが、これの使い方が理解できません。
747 :
デフォルトの名無しさん :2005/06/29(水) 11:18:23
m9
748 :
デフォルトの名無しさん :2005/06/29(水) 15:00:50
たとえばポインタxのアドレスがもう一個のポインタyに入ってるとする。 するとyはxのポインタ、つまりポインタのポインタである。 って事はどうなるの ↓
struct structure_def { char *strings; }; structure_def *structure;
>>748 char c1[3] = "c1"; // c, 1, \0
char c2[3] = "c2"; // c, 2, \0
char* x;
char** y;
x = c1; // xの値はc1のアドレス(c1[3]の先頭アドレス)「100」(仮定)
y = &x; // yの値はxのアドレス「200」(仮定)
printf("xを参照:%s\n", x);
// printf()の第2引数に「*y」を指定する。つまりprintf()の中では
// ポインタの2枚剥がし(xを経由してc1を参照)が行われる。
printf("yを参照:%s\n", *y); // ・・・・・・・・・・・・・(1)
x = c2; // xの値はc2のアドレス(c2[3]の先頭アドレス)「150」(仮定)
//(1)以降はyへの代入を行っていないにもかかわらず以下の結果は(1)と異なる
printf("yを参照:%s\n", *y);
DirectXのメソッドなどだとよくポインタのポインタがある
というよりCOMをCで使おうとするとポインタのポインタはよく出てくる。C++だと参照がある分、楽だ。 それはともかくとして、「引数」に値を代入したいときにはポインタにする。 void f1(int *a, int b) { *a = b; } その「引数」の型がたまたまポインタだったりすると結果はポインタのポインタになる。 void f2(int **a, int *b) { *a = b; } ようするにそれだけなんだけどね。
要するにCでは値渡ししかできないので、参照渡しみたいなことをするためには ボインタのボインタが必要ってことね。
char c1[3] = "c1"; // c, 1, \0 char* x; char** y; char*** z; x = c1; // xの値はc1のアドレス(c1[3]の先頭アドレス)「100」(仮定) y = &x; // yの値はxのアドレス「200」(仮定) z = &y; printf("xを参照:%s\n", x); // printf()の第2引数に「*y」を指定する。つまりprintf()の中では // ポインタの2枚剥がし(xを経由してc1を参照)が行われる。 printf("yを参照:%s\n", *y); // ・・・・・・・・・・・・・(1) // 3枚剥がし! printf("zを参照:%s\n", **z);
昔仕事暇時の遊び(たいした仕事じゃなかった)で 全ての変数を**************つけて定義してみた。 コンパイルしてバイナリ(obj)比較したら変わらんかった。 & -1 * +1 [] +1という感じで差を数えてたのかな。
757 :
デフォルトの名無しさん :2005/07/02(土) 23:47:20
ポインタを経由し無ければできない事って何んですか?
>>757 たとえばこんなとき。
#include <stdio.h>
void f1(int n)
{
n = 64;
}
void f2(int *p)
{
*p = 64;
}
int main(void)
{
int n = 1;
printf("%d", n);
f1(n);
printf("%d", n);
f2(&n);
printf("%d", n);
return 0;
}
ほかにも配列を引数として渡すには問答無用でポインタにするしかないし、構造体もポインタ渡しの方が効率が良いことが多い。
(配列・構造体を引数にするとき、こういう風に関数内で中身を書き換える場合以外はconstポインタを使う。)
759 :
デフォルトの名無しさん :2005/07/03(日) 01:29:03
double **x; x = new double[n][m]; ってアリですか。 ナシなら2次元の場合どうしたらシアワセになれますか
#include <iostream> #define LENGTH 10 #define HEIGHT 5 int main(int argc, char* argv[]) { double **x = new double*[HEIGHT]; for (int i = 0; i < HEIGHT ; i++) { x[i] = new double[LENGTH]; } for (int j = 0; j < HEIGHT; j++) { delete[] x[i]; } delete[] x; return 0; }
761 :
760 :2005/07/03(日) 02:10:13
バグあり。 delete[] x[j];
できた。
>>760 先生にシアワセが訪れますように。
763 :
デフォルトの名無しさん :2005/07/07(木) 16:00:31
c言語で1000以下の素数を二つ足し合わせて1000になるプログラムってどうすればいいんですか?わかる方いましたらお願いします。できるだけ初心者でも理解できるものでお願いします。
>>763 1000以下の素数を求めて、足したら1000になる組み合わせを探す
766 :
デフォルトの名無しさん :2005/07/07(木) 19:17:35
他のとこでも言ってきたのですが、今回書き込みするのが初めてだったのでここのマナーを知らずにすみませんでした。次からは気をつけたいと思います。本当にすみませんでした。
767 :
デフォルトの名無しさん :2005/07/07(木) 21:44:00
死ねクズ
まぁ許してやれよ
769 :
デフォルトの名無しさん :2005/07/07(木) 21:58:58
double **x; x = new double*[n]; *x = new double[n*m]; for(int i=1; i<n; i++) x[i] = x[i-1]+m; delete[] *x; delete[] x;
770 :
デフォルトの名無しさん :2005/07/07(木) 22:12:50
>>764 それは効率が悪くないか?
ゴールドバッハの予想を使えば少し効率良く処理できるかと。
>>38 真実
アセンブラでできることをシンプルに実装してるからなCは
772 :
日本道路公団 :2005/07/08(金) 02:46:05
C言語の学習での山場ってどこですか?
前半の山場はポインタ、中盤はクイックソート、終盤は線形リスト 意外とおもしろいのがインラインアセンブラ
>>771 オ-バー風呂-とか消えてしまない?
Cは何かと不便なきが。
>>775 まずはそのダメダメな日本語を消さないとな
>>774 リストやソートや検索のお勉強で脳ミソからお熱をあげる人(おれ)ってプログラミング向いてない?
ポインタはなんとかクリアしたはずなのにな
>>777 最初は誰でもそう。
初めから全部わかったら天才か基地外。
ポインタちょーうぜー!
一度ポインタの良さを味わったら忘れられない体になる
頭では配列でいいやと思っても 嫌がおうにもポインタを使ってしまう体になる。
初心者って配列にすれば分かりやすくなるところを、なぜか頑張って ポインタ使ってスパゲッティなコード書くよな
>>753 _, ._
( ゚ Д゚) ・・・
_, ._
( ´ Д⊂ ゴシゴシ
_, ._
( ゚ Д゚) ・・・
まあボインタがなくても参照私みたいなことは出来る罠。 ていうかボインタって何ですか?調べたけど解りませんでした
おっぱいが大きい人を参照するのに使う
そいつはボインだ
……って、本当に bo って書いてあるよママンっていうか見間違えてスマヌ
この速度ならぬるぽ
この速度でもガッ
この速度ならぬるぽ
この速度だからガッ
794 :
デフォルトの名無しさん :2005/08/19(金) 23:43:46
あげ
あ?だからさぁポインタつーのは、おまえのマシンについてるメインメモリの番地だろ? おまえのマシンに512MBのメモリが刺さってたら、 ポインタってのは 0〜536870912(512MB) の範囲のメモリ位置をあらわす数値なんだよ。 int a = 100; int* ap = &a; printf("ap=%d\n", ap); とかいうコード書くと ap=2293596 とか表示されるだろ? つまり、おまえのマシンに突き刺さってるメモリの、 2293596番目に変数aの100が格納されてんだよ。 ↓2293596番目 ┏━━━━━━━━━━━━━━┓ ┃ 〜 100 〜 ┃ ←この四角いのがメモリ ┗━━━━━━━━━━━━━━┛ 0 536870912(512MB) まあ、今時のOSはみんな仮想メモリだから、 実際の物理的なメモリの2293596にアクセスしてるかどうかはわからんのだが。
796 :
795 :2005/08/20(土) 00:11:18
ず、ずれた…。 ↓2293596番目 ┏━━━━━━━━━━━━━━┓ ┃ 〜 100 〜 ┃ ←この四角いのがメモリ ┗━━━━━━━━━━━━━━┛ 0 536870912(512MB)
あなる程 分かりやすい 変数をメモリ以上使ったらどうなりますか?
仮想メモリ、MMU
1. >おまえのマシンに512MBのメモリが刺さってたら、 >ポインタってのは 0〜536870912(512MB) の範囲のメモリ位置をあらわす数値なんだよ。 2. >まあ、今時のOSはみんな仮想メモリだから、 >実際の物理的なメモリの2293596にアクセスしてるかどうかはわからんのだが。 2.があやふやだから、1.がおかしい プロテクトモードでも、セグメント切り替え、64kの壁て知ってるか? と、初歩向けの答えに突っ込みを入れてみるw
>799 MMUは変数をメモリ以上使わなくとも使っている、プロテクトモードなら。 そもそもMMUは、物理メモリを論理メモリに変換するCPUの機能 何故、そんなことをするかというと、 ・システムとして重要なアドレスエリアをユーザに使われないようOSがプロテクトモードの階層(権限)(Penに設定できるレジスタがあったと思う)により制限を掛けるため。 (もし、アクセスするとアドレス保護例外(CPUが出す例外)が起こる) ・プログラム同士のアドレスをお互いに侵食しないために利用アドレスを分けている。 (プロテクトモードでユーザから見て0番地でも、実際は全く違う。更に言うと、ユーザから見て0番地が多数存在する) あとは、IDT(割り込みベクタテーブル)のCPUの外から見える存在アドレスを変えることにより、 独自に(OS上に)割り込みベクタテーブルをカスタマイズできるというのもある それと、これはMMUでなく、プロテクトモードの機能だけど、階層(権限)により、システム上重要なアセンブラ命令をユーザに使わせないようにしている>特権命令(OSが設定)
802 :
795 :2005/08/21(日) 01:23:36
>>797 !?なんて柔軟な発想!
>>798 あなる程・・・アナル程・・・。
えーっと、しらん。なんか仮想メモリ的なものでがんばるんじゃないか?
>>800 1.がおかしいのは説明用の文章だから。
2.があやふやなのは、漏れがそこまで仮想メモリについての知識を持ってるわけじゃないから。
803 :
795 :2005/08/21(日) 01:32:23
あ、で、ポインタ型について説明してないね。 ポインタ型は4バイトのメモリアドレスを管理する変数。 ポインタもメモリのどっかに4バイト確保してメモリアドレスの数値を管理するもの。 // コード int a; int* ap = &a; printf("a =%d\n", a); printf("&a =%d\n", &a); printf("ap =%d\n", ap); printf("&ap =%d\n", &ap); // 上記コードの実行結果 a =100 &a =2293596 ap =2293596 &ap =2293592 ↑みたいなコードだと↓みたいなイメージになる。 ↓2293592番目(ap) ┏━━━━━━━━━━━━━━━━━━━┓ ┃ 〜 | 2293596 | 100 | 〜 ┃ ←この四角いのがメモリ ┗━━━━━━━━━━━━━━━━━━━┛ 0 ↑2293596番目(a) 536870912(512MB)
804 :
795 :2005/08/21(日) 01:34:01
>>797 あっ、すいません。三角形は無理ですた。
>803 あ? あせって書かなくていいんだよ。 だいたいなんで、 int* ap = &a とポインタ参照なのに、先頭アドレスが違ってるんだ、そこでおかしいと思わなかったか? で、&apてなんだ? 変数aの指す先頭アドレスは&a 変数apの指す先頭アドレスはapだろう apにある値は*apだろう 図が無茶苦茶だなぁ
806 :
795 :2005/08/21(日) 14:58:55
>>805 ん?どのへんがわからないんだ?
>変数aの指す先頭アドレスは&a
「変数aの指す」というよりは変数aの先頭アドレスはのほうがしっくりくるな。
>で、&apてなんだ?
>変数apの指す先頭アドレスはapだろう
そうだね。それでap自体のアドレスが&apだろ。
俺は最終的にポインタ型はchar*だろうとint*だろうとdouble*だろうと
4バイトの整数型ということが言いたいんだが。
↓のコードでわかるかな。アドレス値を int で受け取ってみた。
int a = 100;
int ap = (int)&a;
printf("a =%d\n", a);
printf("&a =%d\n", &a);
printf("*ap =%d\n", *((int*)ap));
printf("ap =%d\n", ap);
printf("&ap =%d\n", &ap);
a =100
&a =2293596
*ap =100
ap =2293596
&ap =2293592
807 :
795 :2005/08/21(日) 15:09:03
つまり、↓のようなコードを書くとメモリの100番目を int 型のデータとして見る。 int a=100; printf("&a=%d\n", &a); printf("*a=%d\n", *((int*)a)); //実行結果 &a=2293596 (※ここでアドレス保護だかでプログラムが落ちる ↓100番目( *((int*)a) ) ┏━━━━━━━━━━━━━━━━━━━┓ ┃ | 不明 | 〜 | 100 | 〜 ┃ ←この四角いのがメモリ ┗━━━━━━━━━━━━━━━━━━━┛ 0 ↑2293596番目(a) 536870912(512MB) *演算子というのは、中身をアドレス値として評価し、その番地のメモリにアクセスをして見る演算子。 今回は100が入っていたので100番目にアクセスしていって、 100番目はちょっとアクセスしてはいけない領域だったから落ちたと。int*にキャストしてるのはえーと説明めんどい。
>806 さきと変わたな。 >int* ap = &a; が >int ap = (int)&a; になった。 つりだとおもうけど、さっきと状況一変したぞ。 今度は参照ではない。単にアドレス値をint型へ代入してる。 だから、&aと&apのアドレスが違う。 それと、 さきの&apてなんだ?だが、 int* ap と宣言しておいて、int**を求めるいうことか? これは何を意味するのか分からない、 俺の脳みそが足らないだけかもしれないけど。
809 :
795 :2005/08/21(日) 15:35:05
>>808 うーん、そうだな。最終的にポインタ型もデータなのよ。メモリにデータとして確保される。
int* ap;と宣言するとメモリに↓こんな感じで ap のデータ領域が確保される。
↓2293592番目(ap)
┏━━━━━━━━━━━━━━━━━━━┓
┃ 〜 | 不 定 | 〜 ┃ ←この四角いのがメモリ
┗━━━━━━━━━━━━━━━━━━━┛
0 ← 4bytes → 536870912(512MB)
なにも代入していないので中身は「不定」と書かせてもらった。
で、aという変数が2293596番目にあるとして ap = &a; とすると↓のようになる。
↓2293592番目(ap)
┏━━━━━━━━━━━━━━━━━━━┓
┃ 〜 | 2293596 | 100 | 〜 ┃ ←この四角いのがメモリ
┗━━━━━━━━━━━━━━━━━━━┛
0 ↑2293596番目(a) 536870912(512MB)
つまり、ポインタを宣言するのは int型を宣言すると一緒なのよ。
だから、int* ap; を &ap とするとそのデータへの先頭アドレス(2293592番目)が返ってくるわけよ。
上に書いたコードをコンパイルして色々試してみるとわかるよ。
ポインタが4バイトというのは処理系を限定した話だし、 そもそもポインタは、アドレスを格納するだけのものではない。 型付けという重要な役割を持っている。
811 :
795 :2005/08/21(日) 15:38:37
×つまり、ポインタを宣言するのは int型を宣言すると一緒なのよ ○つまり、ポインタを宣言するのは 4byteの整数型を宣言すると一緒なのよ の方がわかりやすいかね。
ちがうな。 つまり、宣言によって、ある一定サイズのメモリエリアが確保されるという意味においては、 ポインタ型も他の組み込み型といっしょなのよ。 というべきだ。
813 :
795 :2005/08/21(日) 15:48:03
>>810 まあ、たしかにね。「初歩を理解する上では」という意味で説明をしたわけよ。
「型付け」に関してもまず何が入っているか説明した方がわかりやすいだろうし。
それに処理系を限定して具体的な話をしたほうがわかりやすいだろ。
なぜポインタが4バイトなのかは、32bit(4bytes) CPUだから4バイトが扱いやすいとか、
今の4バイトのポインタでは、4バイトで表現できる最大の4ギガ(4294967296)までが、
扱えるメモリの限界とか色々まわりのこともわかってくるわけだし。
814 :
795 :2005/08/21(日) 15:54:38
だから 64bit CPU になったときは状況が変わtt
あっ、
>>812 えーと。そうだね。でもそれだと初心者は意味わかんなくね?
だから、
>>1 みたいなまだ理解が浅い人が、
そういう抽象的な説明をされて意味わからなくてこういうスレを建てちゃうわけよ。
int サイズやpポインタサイズは処理系によって違う。 現在多く普及しているWindowsでは、どちらも32bitであることが一般的である。 ここでは、特に断りない場合intやポインタ型は32bit(4bye)として話を進める。 と最初にかいときゃいいじゃん。むしろこういうのが一番大事。
816 :
795 :2005/08/21(日) 16:13:41
>809 それは違うだろう >803でしっかり、 &a =2293596 ap =2293596 アドレス一緒という結果が出ている。 だから、>809のapと&aのアドレスが違っている図はおかしい。 でだ、そちらに参照の確認の意味でいい極短コードを渡すよ。 #include<stdio.h> voidmain(){ inta=1; int* b=&a; printf("%d\n",*b); *b=2; printf("%d\n",a); } .c(c)でも.cpp(cpp)でもどちらでもこのまま試せる
818 :
デフォルトの名無しさん :2005/08/21(日) 16:29:20
>817はintだがcharだと状況は一変してくる #include<stdio.h> #include<string.h> voidmain(){ chara; strcpy(&a,"あい"); char*b=&a; printf("%s\n",b); b="うえ"; printf("%s\n",&a); } Cでは変数は頭で宣言しなければならないから、.cppでないと試せないが、 .cでやるなら、char aの次にchar* b=""とでもしておいて、strcpyの後、b=&aとでもすればいい intでは=は参照を意味したが、charでは代入の様相を呈してくる。 なぜなら、""自体が入れ物(アドレス)だから。 "あい"と"うえ"は違う入れ物だから。 &aがbのアドレスが変わったことを知ることはできない。 =はアドレスだけがコピーされ実体はコピーされていない。 だから、&aの内容は"あい"のままになる。
819 :
795 :2005/08/21(日) 16:33:42
>>817 ん?そうではないとすると、じゃあ↓これはどう説明するんだ?
#include<stdio.h>
void main(){
int a=1;
int a2=999;
int* b=&a;
int** c=&b;
printf("%d\n",*b);
*b=2;
printf("%d\n",a);
*c=&a2;
printf("%d\n",*b);
*b=255;
printf("%d\n",a2);
printf("%d\n",a);
}
820 :
デフォルトの名無しさん :2005/08/21(日) 17:59:36
#include<stdio.h> void main(){ int a=1; int a2=999; int* b=&a; int** c=&b; printf("%d\n",*b); *b=2; printf("%d\n",a); printf("%d\n",b); *c=&a2; printf("%d\n",*b); printf("%d\n",a); printf("%d\n",b); *b=255; printf("%d\n",a2); printf("%d\n",a); } を試したら、途中でbのアドレスが変わったな。 それで、&aのbへの参照が開放された。(&aはbのアドレスが変わったことは分からないから、a=2という実体だけが残る) おそらくbのアドレスが変わったのはint**cの影響だと思うけど、まだint**が分かんないなぁ こんな程度ですまないね
821 :
デフォルトの名無しさん :2005/08/21(日) 18:39:25
もしかして、**てアドレッシングと関係あるのかね、アドレスのアドレスて。 Pentiumの持ってるアドレッシング方式と、OSがコードを翻訳したとき放つ命令セットを分かってないけど &bが4byteスライドして動いている
失礼 >OSがコードを翻訳 >コンパイラがコードを翻訳
憶測の域を出ないけど int*でebp(ベースアドレス)+esi(インデックス)を表し int**でebp(ベースアドレス)を表すんじゃないかなと思た 32bitの場合にはesiで4byteじゃないかなと int** c=&b; でベースインデックスアドレス指定だったのが *c=&a2; でベースアドレスをしていていて、それでアドレスが4byte動いたのかなと 推測ですみませんね 違っていて、もしよかったら指摘してください
キモイレジスタなんかどうでもいいよ
825 :
795 :2005/08/21(日) 22:47:25
うーん、↓で納得できんかね? int a=100; int ap = &a; int app = ≈ printf("a=%d\n", a);// a=100 printf("&a=%d\n", &a);// &a=2293596 printf("ap=%d\n", ap);// ap=2293596 printf("*ap=%d\n", *ap);// *ap=100 printf("&ap=%d\n", &ap);// &ap=2293592 printf("app=%d\n", app);// app=2293592 printf("*app=%d\n", *app);// *app=2293596 printf("&app=%d\n", &app);// &app=2293588 ↓2293588番目(app) ↓2293596番目(a) ┏━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ 〜| 2293592 | 2293596 | 100 | 〜 ┃ ←この四角いのがメモリ ┗━━━━━━━━━━━━━━━━━━━━━━━┛ 0 ↑2293592番目(ap) 536870912(512MB) ポインタも単に「整数値」を保存するデータ型。 appは2293588というアドレスに「2293592」という整数を保存した整数データ。 apは2293592というアドレスに「2293596」という整数を保存した整数データ。 aは2293596というアドレスに「100」という整数を保存した整数データ。 ゆえにひねくれた解釈をすると、 *app は *((int**)2293592) と等価。 *ap は *((int*)2293596) と等価になる。
826 :
795 :2005/08/21(日) 22:49:15
もしここで b という変数を追加したとするとこんな感じになる。
int b=200;
int a=100;
int* ap = &a;
int** app = ≈
↓2293588番目(app) ↓2293596番目(a)
┏━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 〜 | 2293592 | 2293596 | 100 | 200 | 〜 ┃ ←この四角いのがメモリ
┗━━━━━━━━━━━━━━━━━━━━━━━┛
0 ↑2293592番目(ap) ↑2293600番目(b) 536870912(512MB)
こういう状況でもし↓こういうコードを書いたとしたら、
*app = &b;
↓2293588番目(app) ↓2293596番目(a)
┏━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 〜 | 2293592 | 2293600 | 100 | 200 | 〜 ┃ ←この四角いのがメモリ
┗━━━━━━━━━━━━━━━━━━━━━━━┛
0 ↑2293592番目(ap) ↑2293600番目(b) 536870912(512MB)
&bは2293600なので、apの中身が 2293596 から 2293600 に変わると。
この状況では、apは2293600をさしているので *ap=400 とかやると、
b(2293600)の中身が 400 に変わると。
>>823 レジスタとかわからんちん。
827 :
795 :2005/08/21(日) 22:50:44
微妙に図中の矢印がずれた('A`)
828 :
795 :2005/08/21(日) 23:22:16
でも、上記のポインタを「メモリアドレスを格納する整数値」で実装する方法は、
MSのC言語とかGCCのC言語による、ポインタの実装であって、
C言語の仕様としてはポインタは整数値で管理しているとは記されてはいないというのを読んだことがあるけど。
・・・って
>>532 ここかぁー!
でも今後、新しいCコンパイラが出たとしても、
このポインタを「メモリアドレスを格納する整数値」で実装する方法は変わらないでしょうね。
大体のコンパイラでは、こういう実装なのに
>>532 みたいな発言するのは初心者が混乱するんでやめてほしい。
gccは、どうなるかわからんぞ。4.0で中間言語を一回はさむようになってるからな。 ポインタがアドレスである必要はないし、むしろそういう規定は柔軟性を損なわせる。
830 :
795 :2005/08/21(日) 23:38:18
>>829 (;・∀・)ちゅ、中間言語・・・?Javaのようになるん!?
ぼくのしってるgccもかわっちゃったなぁ。というか最近のC言語もすごいなぁ。
そうなると俺もC言語のポインタってなんですか?っていうスレたてちゃうかも('A`)
>>830 中間言語の存在はコンパイル中だけで出力されるオブジェクトファイルは機械語だよ。
832 :
デフォルトの名無しさん :2005/08/22(月) 11:38:24
>>829 中間言語(仮想コード)にするのは 4.0 以前からやっていた筈だけど?
4.0 は各言語に合わせた最適化をするようになったんだと思った。
ポインタってだけで一冊本ができてしまいますよね.
834 :
デフォルトの名無しさん :2005/08/22(月) 14:06:15
>>833 1冊ではありません。amazon.co.jp で「C ポインタ」をキーにして
和書の検索をすると17冊出てきます。
835 :
デフォルトの名無しさん :2005/08/22(月) 14:20:06
ポインタのポインタとかって使うの?
Herbert Schildtが言うには後々便利なことが分かるらしいです.
837 :
デフォルトの名無しさん :2005/08/22(月) 14:32:12
>>835 文字列の配列とかで使いますね。
例
char *s[] = {"Hello", "2ch"};
DirectXを使ってる時もポインタのポインタ出まくりんぐ
>>835 たとえばこんな感じに。
void GetMem(void **pp)
{
*p = malloc(0x100);
}
別に普通の型へのポインタと変わらない。
void GetRand(int *p)
{
*p = rand();
}
C++慣れている奴でも クラスのメンバ関数の関数ポインタ型の定義を書けと言われて 即時答えられる奴は少ない
>>840 そこにコンパイラがあればささっと書くだけ。
#include <iostream>
#include <typeinfo>
struct hoge
{
void f();
};
int main()
{
std::cout << typeid (&hoge::f).name() << std::endl;
}
>>840 たしかに。定義としかも呼び出し方法も即答できないね。あれは。
Klass k;
void (Klass::*aho)(void) = &Klass::method;
((k).*aho)(); // インスタンスにメソッドポインタを関連付けて呼び出し
こりゃねえだろ → ((k).*aho)()
それとも、もっと簡単にかける?
>>843 まじだ。できた。
それでもまだ数日後に覚えていられるかは微妙(笑
もしかしてふつうの関数ポインタが fp(); と (*fp)(); のどっちでもコールできるの知らないのか?
>>844 .と*の二つで.*となって一つの演算子。->*は三つで一つの演算子。
というように覚えると早い。->が-と>に分けられないのと同じで。
>>845 普通の関数ポインタはそうなんだが、C++のメンバへのポインタを使って関数呼び出しするときには844のようにするしかない。
>>845 それは知ってる。
むしろ
(******************fp)();
でも呼べるのも知ってる。
>>846 おお、それはおぼえやすいかもしれん。
生産的なことに労力を使おう。
".*"も"->*"も、そのものが一つの演算子なんですよ。 意味無いけどオーバーロードできるし。
>>850 .*はオーバーロードできない。 . もオーバーロードをできないからそれに合わせて。
ポインタが他の変数のアドレスを入れる変数ってことはわかったけど ポインタという変数のアドレスへのポインタはどの変数が持っているの?
>>852 変数を使ったコードで命令と一緒にパラメタとして使われてる。
なんでアドレスを格納するのにポインタって型が必要なの?
>>854 別にポインタって型が必要といわけでは無いのだが、
ポインタって型がないとポインタと単なる整数の区別がつかなくてさらにバグを生み出す原因に
>>854 大量のデータが必要でも、動的に確保できるので、実行時に使用するメモリを減らせる。
また、サイズの変更が容易になる。
大量のデータでもアドレス計算を少なくして処理できる。
アドレスを単純に増加させてもオフセットの取り方で連続したメモリにならない。
その境界部分の演算が遅くなる原因になるがポインタを使えば境界を越える演算が減らせる。
コード記述で、名前に依存しない記述が可能になる。
同じ関数内で少ないコードで多彩な動作が可能になる。
こんなところだと思う。
857 :
856 :2005/08/27(土) 18:57:07
>>855 あ、そうそう。そうだ。
MSのファイルポインタとか全然ポインタじゃないのにポインタとか・・・
unsigned long ときたらアドレスと思うよーに!
あとは型付けな。 勝手に型をつけてくるのは、場合によっては邪魔になることもあるが。
860 :
デフォルトの名無しさん :2005/08/29(月) 16:44:00
ポインタを解りずらくさせてる要因ってなんだ?
使う機会が少ないから熟練しない
>>861 いや、画像処理とかで使いまくりなんだが
「ポインタは難しい」っていう先入観と、 解説する人間の数だけ増えるポインタの例え方 クラスにも通じる物がありますね
クラスって「オブジェクト指向」って言葉を使うから悪いんじゃね? 「オブジェクト指向」って言葉には殆ど意味なんてないし。 OOAとかOOPとか、後に何か付いてやっと意味になる。
>858 32bit用コンパイラでもポインタのサイズ全部が32bitだと思ったら大変危険。 >860 C言語の仕様だとおもう。
>>865 Linuxは全部こうなんだけど、そろそろどうなんだろうね
せめてuintptr_t
870 :
デフォルトの名無しさん :2005/08/30(火) 18:59:49
UNIXにはポインタをint扱いするプログラムがいまだに溢れてる
>>870 ポインタとかアドレスを unsigned long と扱うコード
>>873 今となってはもはや昔ながらの伝統以外の意味は全くない
875 :
デフォルトの名無しさん :2005/08/31(水) 16:54:40
ポインタってどういう場面で使用されるんですか?
ポインタを多用するプログラムってどんなのがあるのでしょうか
Windows プログラム
Lisp処理系
881 :
デフォルトの名無しさん :2005/10/04(火) 12:52:03
ポインタ〜ッチ。いやぁ〜ん,まいっちんぐ。
まだこのスレあったのね。 ポインタはね、関数で複数の戻り値を返したい時にとても便利なんだお。 普通はreturnで一個しか返せないんだお。
>>883 戻り値は構造体のポインタであって
構造体そのものではない罠
構造体を返して何が悪い。
886 :
デフォルトの名無しさん :2005/10/08(土) 12:09:06
>>885 構造体は返せない。
構造体のポインタは返せるが。
構造体と構造体のポインタは別物。
そういうこと言ってるから、陰で時代錯誤の老害って言われるんだよ
事実なんだけど… 嘘教えるより100倍マシだと思うけど…
構造体返せるだろ?
つい最近返せるようになった。
>>889 構造体を返すプログラムのソース挙げて見れ。
つい最近?
typedef struct { int a,b,c,d; } E; E foo(E ee){ return ee; }
ANSIで標準化された1989年の時点で 構造体は返せるし渡せるようになっているんだけど > 嘘教えるより100倍マシだと思うけど… などと言いながら、平気でウソを教える。 だから「老害」なんだよ。
標準関数にもdivとか構造体を返す関数がある。
構造体が大きいとスタックに積む時間が何だかアレな気はする
まあ、構造体を返す関数の場合は、 一般的な実装では、暗黙の第一引数として呼び出し側がアドレスを渡して そこに代入するんだけどな。 あと、レジスタで渡せるサイズだったらレジスタで返す実装もあった。 もちろん、渡す場合は全コピーだけど。
その昔、異様に大きな配列メンバを持つ構造体を定義して、 実体を返してみたら、実行速度が物凄く遅くなってワロタ。 Cでも配列を実体で返せる方法だと、馬鹿そのものの歓び方をした。
かって知ったる構造体なら値渡しでもいいがな。
気分的に32byte超えると悪いことしてる気がしてしまう いや、なんとなく
まあ俺は32bit超えると悪いことしてる気がするが。
つまりグローバル変数しか使わないってことかい?
ポインタを返すんだろ
1byteじゃなくて32bitに限定しているから、64bitアプリでは破綻。 しかし16bitアプリでは二つのポインタが!!
二つのボイン
64bitアプリでも今の規格ではポインタは32bitだよなぁ確か。
↑ 寝言は寝て言え
mixi でも糞壁って猛威を振るってんだな。 int* p; でも int *p; でも好きにすりゃええやん。
910 :
デフォルトの名無しさん :2005/10/18(火) 19:37:20
>>894 ANSI 以前の C でも構造体は返せるようになっていた。
しかしその後流行出したPCでのCコンパイラの実装では
使えないようになっているサブセットのやつが多かった。
実際使うと恐ろしく遅くなることがあって、使えても
使う人は少なかったのではないかと思う。
構造体を返す変数・・・fopenとか?
変数じゃねぇな関数だ(´Д`;)
fopenが返すのはポインタだが
巨大な構造体返す関数書くと戻り値を、コピーせずに 呼び出し側のスタックに直接書き込む言語もあったりするな。
>>916 最適化具合でそうなるコンパイラもありえるんじゃね?