重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

Buffer[] が定義されている状態で

unsafeモードでの
 byte* pp = (byte*)Buffer;
 byte[] buf = (byte []) Buffer;
では、pp とbuf は何がちがうのでしょう?

どちらも、pp[i], buf[i] で同じデータにアクセスできると思うのですが、違いはどこにありますか?
処理速度的に違いはあるのでしょうか?

なお、
 safeモードの、buf[]では添え字チェックが行われる。
 ポインタは safeモードでは使えない
ということは承知しています。

A 回答 (4件)

他の回答は読みました。

そのうえで。
unsafeモードにした時点で、そこはCの世界です。

ポインタアクセスと配列アクセスについても同様で、
ただ1つの要素にアクセスするだけなら処理速度に差はないでしょうが、
forループで回し続けたりすれば、indexerを見るよりもポインタアクセスのほうが速いでしょう。

また、indexerの値チェックはされません(これもCと同じ)。
    • good
    • 0
この回答へのお礼

>unsafeモードにした時点で、そこはCの世界です。
明快な回答、ありがとうございます。

となると、
>forループで回し続けたりすれば、indexerを見るよりもポインタアクセスのほうが速いでしょう。
が理解できなくなりました。

byte* pp = (byte*)Buffer;
byte[] buf = (byte []) Buffer;

for(int i=0; i<n; i++) {
 pp[i]=i;
}
for(int i=0; i<n; i++) {
 buf[i]=i;
}
は全く同じコードに翻訳されると思うのですが・・・

お礼日時:2018/07/30 22:39

>for(int i=0; i<n; i++) {


> pp[i]=i;
>}
>for(int i=0; i<n; i++) {
> buf[i]=i;
>}
>は全く同じコードに翻訳されると思うのですが・・・

そりゃ同じでしょう。
処理速度の違いは定義じゃなくアクセスの仕方によります。

逆に

for(int i=0; i<n; i++, pp++) {
 *pp=i;
}
for(int i=0; i<n; i++, buf++) {
 *buf=i;
}

も、pp, bufの定義に関係なく速度は同じでしょう。

繰り返しますが、処理速度の違いは定義じゃなくアクセスの仕方によります。
    • good
    • 0
この回答へのお礼

>繰り返しますが、処理速度の違いは定義じゃなくアクセスの仕方によります。
つまり
 bufとppでは同じ
 アクセスの違いとしてbuf[i]と*buf では、*bufのほうが速い(場合がある)
ということですね。

今回の
>pp[i], buf[i] で同じデータにアクセスできると思うのですが、違いはどこにありますか?
>処理速度的に違いはあるのでしょうか?
の直接の回答ではなく、おまけ情報ですね。ちょっと混乱しましたが、回答の意味、理解できました。
ありがとうございました。

お礼日時:2018/07/31 10:50

>エッ? どちらも参照も代入もできますけど?


恐らくポインタの意味自体を理解されていませんね。

ポインタというのはそのデータの格納されているメモリのアドレスを引き渡す機能です。
一方配列というのは言語による違いはありますがC#の場合、配列の長さ、データを格納する領域、及び、チェックロジックから成立しています。

ポインタはその場所を参照に必要なデータをもっているのに対し、配列はデータそのものが代入されています。
ポインタの場合は先頭のアドレスのみを受け渡せばよい為、パフォーマンス面では有利です。
一方でポインタの場合、予約された領域外にもアクセスできてしまいバグの原因になるばかりか、最悪の場合突然OSにプロセスKillされる事になります。

C#の場合ref(参照渡し)や、readonly ref(参照読み取り専用渡し)と言う事が可能です。
refを利用する事で、ポインタの様なパフォーマンスの良さと配列の予約外の領域へのアクセスを未然に防げるという両方が可能になります。
readonly refを利用する事で、refの利点に加えて、値渡しの様に予期せぬ元データの書き換え阻止ができます。

C#2.0まではパフォーマンスの都合でどうしてもポインタを使わざるおえないところがありました。
ですが今のC#では適切な参照渡しを行えばポインタと同程度に高速で、ポインタを使った場合よりも安全なソースコードを記述することができます。
代替機能の完成度が高く、ポインタを使っても碌な事になりません。

unsafeのキーワードが出てきた時点で何かおかしな事をしようとしていると思ってください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます
>恐らくポインタの意味自体を理解されていませんね。
説明いただいた内容はすべて承知しています。その上での質問です。

>unsafeのキーワードが出てきた時点で何かおかしな事をしようとしていると思ってください。
「添え字チェックを省略する」というある意味「おかしな事」を実現しようとするプログラムですが、それは作者が意図したことです。

繰り返しになりますが質問では、
 unsafeモードで配列とポインタの違い
です。
配列の場合、unsafeモードにしても、添え字チェックが行われるということでしょうか?
作者の意図とおり、添え字チェックが行われないのであれば、ポインタとの違いはどこにあるのでしょうか?
C言語のように、ポインタと配列は同一と思ってよいのでしょうか?
という質問です。

よろしくお願いします。

<おまけ>
以下のことを理解したうえで作成されたプログラムです。

for(int i = 0; i < a.Length; i++)
{
a[i] = i; // これは添え字チェックされない
}
for(int i = 0; i < n; i++)
{
a[i] = i; // これは添え字チェックされる
}

お礼日時:2018/07/30 06:07

参照と代入の違い

    • good
    • 0
この回答へのお礼

>参照と代入の違い
エッ? どちらも参照も代入もできますけど?

<参照>
byte a,b,c,d;

a = pp[i];
b = buf[i];

<代入>
pp[i] = c;
buf[i] = d;

お礼日時:2018/07/29 15:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!