2017-02-04 6 views
1

どのような状況で私はそれのよりトリッキーな形を使用する必要がありますか?より高速なバイナリコードを生成しますか?私が[] []記法で仕事をすることができれば、何らかの理由でさらに努力を払い、指針で実装すべきでしょうか? 単一データの場合、私はポインタの必要性を理解しています。私は具体的に2次元配列を求めていますが、ポインタを使用する一般的な意味については求めていません。C++で "array(i)[j]"に "*(*(array + i)+ j)"を使用する理由は?

+5

あなたが維持しなければならない人を憎む場合にのみ、難読化コードのコンテスト –

+6

使用を入力していますそのコード。 –

+0

私はこれが冗談だと​​知っていますが、注意してください。@MikelF。ポイズン・ピルコードの後ろにいれば、狩りをするときにあなたの周りをフォローする方法があります。あなたが訴訟であなたに不利な証言としてそれを使用する場合、あなたは決して知らないのです。 – user4581301

答えて

5

どのような状況で私はそれのよりトリッキーな形を使用する必要がありますか?

決して@M.M' comment

に述べたように、コードの難読化コンテストに出席している場合を除き、それはより速く、バイナリコードを生成していますか?

いいえ、放出されたアセンブリ命令は、まともなコンパイラと同じでなければなりません。

私はまだ何らかの理由で余計な努力をしてポインタで実装する必要がありますか?

いいえ標準のコンテナまたはスマートポインタを代わりに使用してください。生のCスタイルの配列とポインタは使用しないでください。

既知の大きさのために最も簡単な方法は、サイズがvariying 2Dアレイの場合

std::array<std::array<T,5>,10> array2D; 

は、あなたが考える、連続した動的メモリブロックを使用する2D配列を最適化するには

size_t rows, columns; 
std::cout << "Enter row and column size please > " << std::flush; 
if(std::cin >> rows >> columns) { 
    std::vector<std::vector<T>> array2D(rows,std::vector<T>(columns)); 
} 

を使用することができますです行と列のオフセットを内部値の位置に変換する小さなラッパークラスを作成します(例:std::vectorのように単純に保持します)。

1

@πάνταῥεῖのアドバイスに加えて、C++式を書くことが好ましいので、同様の型を変数に置き換えることができます。つまり、原則汎用コードです。

std::arrayは、C配列の代替手段です。 (2次元の場合はstd::array< std::array< int, M >, N >のようになります)+演算子はサポートされていません。そのため、難読化された式は、その型への移動や、std::vectorなどの他のコンテナのような型を妨げます。

+0

に... STDの2次元の場合を試してみましょう::配列は、配列へのポインタを必要とし、単一の次元のベクトル、我々はAPIに供給できるのメモリとは異なり、しかしPOD-互換性がありません。ありがたいことに、2次元配列を使用するAPIはあまりありません(少なくともCADシステムを扱っていない場合) – Swift

+0

Clarify? C++ POD =標準レイアウトと簡単。 'array 'はPOD TのPODです(病理学的な配列以外の非静的データメンバーを持っていない限り)。これには、2次元の場合も含まれます。一方、 'std :: vector'は決してPODではありません。 CライブラリとABIとの互換性を保証する唯一の方法は、二次元のC配列としてCからタイプを使用することである - に等しく、それは 'のstd :: vector'配列にそのようなアレイを別名するUBを(または' 1次元または2次元の「std :: array」)。 – Potatoswatter

+0

のstd ::ベクトルとstd ::アレイは(連続するストレージを有し、データを介して下層のアレイへの直接アクセスを提供する)方法が、STD ::アレイ<スタンダード::アレイ< T, M >、N>ありません。明らかに非PODであるstd :: array < T, M >を参照して、連続したストレージを持っています。多次元配列も連続していることが保証されているので、私の答えで書いたものとは逆の方法でdata()によって返されたポインタを使用するのはUBではありません。 – Swift

0

array[i]フォームよりも*(array + i)フォームを好む理由は一般的にありません。同様に、array[i][j]より*(*(array + i) + j)フォームを好む理由もありません。

意味的にはそれらは同等であり、コンパイラはより効果的な "バイナリコード"を発行することができます - どちらの場合も通常は同じです。

実際には、人間は通常array[i][j]形式を理解しやすくなりますので、人を混乱させたくない場合(難読化など)は好ましくありません。

ポインタ計算の他の形式を使用する場合は、等価を理解することが不可欠です。これにより、技術のより効果的な選択が可能になります。 C++標準ライブラリがイテレータ(ポインタの一般化された形式)をサポートしていて、範囲を扱うのは偶然ではありません。

0

2d配列の仕組みについて説明します。その式は、配列が多次元である場合、配列の名前を使用して起こりうる誤りの反例です。まれなミスではないとしましょう。多くの経験の浅いプログラマは何をすべきか:

最良のシナリオで
int arr[10][20]; 

for (int I =0; I<200; I+=1) *(arr + I) = <some value based on I>; 

、彼らは「INT」に「int型から変換することはできません[20]」エラーが発生し、その優れた(またはそれにSOウェブサイト)にアクセスしてください。最悪の場合、それらは "巧妙"になり、コンパイラを欺くために型キャストを使用します。それはK & R以来、すべての本であるため、

彼らは、どのように単一次元配列の仕事を知っている、と彼らは私が9表現よりも大きくなるとすぐにバインドされた配列の外に出ていることに気付いていない

*(*(arr + i) + j) 

は、配列のインデックスが、その配列の名前が劣化したポインタに対して乗法的であることを示しています。彼らが望むものを行うにはより多くの「適切な」方法はintへのポインタを使用することです:

int *p = (int *)&arr[0][0]; 

for (int I = 0; I < 200; I++) 
    *(p+I) = <some value based on I; 

しかし、厳密に言えば、あなたがunsigned char型へのポインタを使用しない限り、C++標準では、このいずれかを保証するものではありません。

プラットフォームの場合、パディングが想定され、配列の要素が実際には末尾にパディング(たとえば構造体)が必要な型の場合は、ここでも注意が必要です。

我々の出力結果の配列は、場合:

cout << "arr[][] = { "; 
for (int i = 0; i < 10; i++) 
{ 
    cout << "\n{"; 
    for (int j = 0; j < 20; j++) 
     cout << arr[i][j]<< " "; 
    cout << "}"; 
} 
cout << "}\n"; 

は、我々は得るでしょう:

arr[][] = { 
{0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 } 
{20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 } 
{40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 } 
{60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 } 
{80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 } 
{100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 } 
{120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 } 
{140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 } 
{160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 } 
{180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 }} 
関連する問題