Google グループは Usenet の新規の投稿と購読のサポートを終了しました。過去のコンテンツは引き続き閲覧できます。
表示しない

pointer

閲覧: 7 回
最初の未読メッセージにスキップ

ca...@xxx.kgc.co.jp

未読、
2004/04/14 2:00:312004/04/14
To:
C89 の配列またはポインタで、
例えば引数が 1 から 3 の配列を疑似的に表現しようと、

int vv[3], *v = &vv[-1];
v[1] = v[2] = v[3] = 0;

または

int *vv = malloc(3 * sizeof(int)), *v = vv - 1;
v[1] = v[2] = v[3] = 0;

のように、配列や malloc した範囲の外を指すアドレス
(この場合 vv - 1)を参照することは、
意図の通りに動くことが保証されているのでしょうか?

神田敏広 <ca...@kgc.co.jp>

Takao Ono

未読、
2004/04/14 2:28:402004/04/14
To:
小野@名古屋大学 です.

<s7f65c3...@xxx.kgc.co.jp>の記事において
ca...@xxx.kgc.co.jpさんは書きました。
candy> C89 の配列またはポインタで、
candy> 例えば引数が 1 から 3 の配列を疑似的に表現しようと、
(snip)
candy> のように、配列や malloc した範囲の外を指すアドレス
candy> (この場合 vv - 1)を参照することは、
candy> 意図の通りに動くことが保証されているのでしょうか?
ほとんどの処理系では意図した通りに動作すると思いますが, C99 の規
格によると undefined behavior です. C89 の規格は持ってないけど,
C89 でもそうじゃなかったかなぁ.

C99 では Appendix J Portability issues の J.2 Undefined behavior
の中に
Addition or subtraction of a pointer into, or just beyond, an
array object and an integer type produces a result that does not
point into, or just beyond, the same array object.
とあります.

int vv[3], *v = &vv[-1];


int vv[3], *v = vv+(-1);
と等価 (6.5.3.2 Address and indirection operators の paragraph 3)
で, この vv+(-1) が上の条件にあてはまるから undefined behavior に
なります.
# どうでもいいけど &vv[3] は OK.
--
名古屋大学大学院 情報科学研究科 計算機数理科学専攻
小野 孝男

ca...@xxx.kgc.co.jp

未読、
2004/04/14 3:30:382004/04/14
To:
御回答ありがとうございます。

ta...@hirata.nuee.nagoya-u.ac.jp (Takao Ono) writes:

> C99 では Appendix J Portability issues の J.2 Undefined behavior
> の中に
> Addition or subtraction of a pointer into, or just beyond, an
> array object and an integer type produces a result that does not
> point into, or just beyond, the same array object.
> とあります.

> int vv[3], *v = &vv[-1];
> は
> int vv[3], *v = vv+(-1);
> と等価 (6.5.3.2 Address and indirection operators の paragraph 3)
> で, この vv+(-1) が上の条件にあてはまるから undefined behavior に
> なります.

やはりそうですよねえ……
malloc した領域も array object と考えていいんですよね?

元ネタは
<URL:http://www.numerical-recipes.com/pubdom/nrutil.c.txt>
なんですが。


> # どうでもいいけど &vv[3] は OK.

これが合法的に参照できないと不便でしょうがないので、
どうでもよくありません。

神田敏広 <ca...@kgc.co.jp>

Yasushi Shinjo

未読、
2004/04/17 1:46:502004/04/17
To:
新城@筑波大学情報です。こんにちは。

In article <s7f65c3...@xxx.kgc.co.jp>


ca...@xxx.kgc.co.jp writes:
> 例えば引数が 1 から 3 の配列を疑似的に表現しようと、
> int vv[3], *v = &vv[-1];
> v[1] = v[2] = v[3] = 0;

配列の引数じゃなくて添字ね。そういうことなら、これでいいんじゃ
ないですか。

int vv[3+1];

それで、v[0] は使わないことにします。一貫性をもって v[0] を
使わないなら、それで用は足りているはずです。

あと、Cでそういうことをするには、常套手段としては、マクロを
使います。たとえば、

#define v(i) vv[i-1]

としておいて

< v(1) = v(2) = v(3) = 0;

と書くと

< vv[1-1] = vv[2-1] = vv[3-1] = 0;

と展開されます。引算入っていますが、別に最近のコンパイラや
CPUなら遅くはならないと思います。と言った、int *v の間接
より速いとは言いにくいけど、速そうな気もします。

丸い括弧は、Fortran みたいだし。いいんじゃないですか。

\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報       \\

IIJIMA Hiromitsu

未読、
2004/04/17 8:22:242004/04/17
To:
いいじまです。重箱の隅。

> #define v(i) vv[i-1]
> としておいて
> < v(1) = v(2) = v(3) = 0;
> と書くと
> < vv[1-1] = vv[2-1] = vv[3-1] = 0;
> と展開されます。

一応の作法として、
#define v(i) vv[(i)-1]
としたほうが無難かと。

v(x=y) などとされたらたまったものではありません。

========================================================================
飯嶋 浩光 / でるもんた・いいじま http://www.ht.sakura.ne.jp/~delmonta/
IIJIMA Hiromitsu, aka Delmonta mailto:delm...@ht.sakura.ne.jp

ca...@xxx.kgc.co.jp

未読、
2004/04/18 20:43:052004/04/18
To:
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes:

> 配列の引数じゃなくて添字ね。

う、なんか書いてて違和感あったのはこれだったのか。
御指摘ありがとうございます。


> int vv[3+1];
>
> それで、v[0] は使わないことにします。一貫性をもって v[0] を
> 使わないなら、それで用は足りているはずです。

まあそうなんですが、別記事にも書きましたように、元ネタは
<URL:http://www.numerical-recipes.com/pubdom/nrutil.c.txt>
で、なにやら数値演算のパッケージの一部らしいのです。
で、オフセットは 1 に限らず(負も含め)任意にしたいみたいですね。
現実には 0 か 1 以外で使うことは、ほぼないでしょうけど。
このコードには matrix() という二次元版もありまして、
オフセットが大きくなると、ムダも大変大きくなると。


> あと、Cでそういうことをするには、常套手段としては、マクロを
> 使います。たとえば、
>
> #define v(i) vv[i-1]

飯島さんの指摘もありますが、 i は (i) でしょう。

<URL:http://www.numerical-recipes.com/news.html>
によると、最新版(売りもの)では
| vectors and matrices are now zero-based!
と自慢しているので、たぶんその類の実装に変えたのだと思います。


> 丸い括弧は、Fortran みたいだし。いいんじゃないですか。

これウケました。すごくいいと思います!!
オフセットを 1 にしたいという要求が、
そもそもはおそらく FORTRAN のコードを使いたいということだと思いますので。

でも配列名もマクロに組み込むと
#define index(v,i)
とかなって見苦しいですね。
LISP みたいでいいか?

神田敏広 <ca...@kgc.co.jp>

Yasushi Shinjo

未読、
2004/04/19 10:53:512004/04/19
To:
新城@筑波大学情報です。こんにちは。

In article <s7f3c70...@xxx.kgc.co.jp>


ca...@xxx.kgc.co.jp writes:
> まあそうなんですが、別記事にも書きましたように、元ネタは
> <URL:http://www.numerical-recipes.com/pubdom/nrutil.c.txt>
> で、なにやら数値演算のパッケージの一部らしいのです。
> で、オフセットは 1 に限らず(負も含め)任意にしたいみたいですね。

Pascal みたい。v : array[-128..127] of integerだったかなあ。
あ、Pascal の文法忘れている。

Cでやるなら、こんな感じ。

struct array
{
int lower ;
int upper ;
int data[0];
};

#define ref(a,i) ((a)->data[(i)-(a)->lower])

まあ、せっかくやるなら、添字の範囲チェックもしたいですね。

#define ref(a,i) (((a)->lower <= (i) && (i) < (a)->upper) ? \
((a)->data[(i)-(a)->lower]) : exit(1))

突っ込みがあったので、括弧を増やしてみました。

> でも配列名もマクロに組み込むと
> #define index(v,i)
> とかなって見苦しいですね。

そういう時には、ローカル・マクロ。

struct array *_v;
_v = malloc(sizeof(struct array)+256*sizeof(int));
v->lower = -128 ; _v->upper = 128 ;

#define v(i) ref(_v,(i))
v(10) = 100 ;
#undef v

新着メール 0 件