【发布时间】:2016-04-19 12:57:42
【问题描述】:
我发现了一个数组的以下实现,它的长度存储在“内部”。代码如下:
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*?对痛觉有任何影响吗?
【问题讨论】:
-
这是一个可怕的黑客攻击。使用带有灵活数组成员的
struct。 -
这当然是有问题的。但是,您可以简单地拥有一个带有表示大小的整数的结构(为此使用
size_t)和double的灵活数组成员。 -
双精度数组可能没有正确对齐。除此之外,代码似乎已定义。也许指针运算应该使用 unsigned char 完成。
-
为什么还是
double? -
((int*)arr)++;格式不正确;++只能应用于左值。也许你的意思是arr = (double *)((int *)arr + 1);
标签: c arrays pointers memory-management