私は長さが "内側"に格納されている配列の次の実装を発見しました。ここでは、コードは次のとおりポインタalingmentと配列の長さの格納
double* construct(const size_t nElements)
{
double* arr = malloc(sizeof(double) * nElements + sizeof(int));
int i = 0;
*(int*)arr = nElements;
((int*)arr)++;
for (i = 0; i < nElements; i++) arr[i] = 1.0 * i;
return arr;
}
void destroy(double* arr)
{
free((int*)arr - 1);
}
void print(double* arr)
{
int N = *((int*)arr - 1);
int i = 0;
printf("Supplied array of %d elements:\n", N);
for (i = 0; i < N; i++) printf("%d : %f\n", i, arr[i]);
}
int main(void)
{
double* a = construct(10);
print(a);
destroy(a);
return 0;
}
この技術の背後にある考え方は、配列の長さを格納するために追加のスペースを有するメモリブロックを割り当て、そしてユーザーにのみポインタ実際のデータ開始を得ました。しかし、私はポインターキャストの点でこの特定の実装で何か怪しいと思う(doubleからint *へ)。
これは一般に許可されていますか?
「はい」の場合、ポインタの位置合わせはどのように機能しますか?
良いアプローチがありますか?
更新: このコードは「ハック」なので、これは悪いことが分かります。私はちょうど何が壊れているのか、理由を知りたい。
所定の回答のほとんど要約: 線((int*)arr)++;
1)のみMSVS
2)下でコンパイルを悪い形成されてはsizeof(INT)ずれべき次のアドレスを引き起こすオフセットを行います二重境界によって。
これは明らかですが、キャスト自体がdouble *からint *に許可されていますか?どのようにしてalingmentに影響を及ぼしますか?
これはひどいハックです。 _flexible配列member_とともに 'struct'を使用してください。 – Olaf
これは確かに疑わしいです。しかし、サイズを表す整数(これには 'size_t'を使います)と柔軟な配列メンバ' double'を持つ構造体を単純に持つことができます。 – EOF
二重配列が正しく整列されていない可能性があります。それ以外では、コードが定義されているようです。たぶんポインタの算術演算は、unsigned charを使って行われているはずです。 – 2501