我们用它来指示一个带有符号*
的指针。迭代该过程,我们获得“双”指针**
,“三重”指针***
,以及更一般地,“d维”指针(对于每个d正自然数)。创建一个d维指针
问题:给定这样一个d作为输入,将S定义为d维指针。
因为我几天前才开始研究动态结构,所以我很不幸地遇到了这个问题。 有没有人有建议/提示?
非常感谢您的提问,对于我可能过于基本的问题表示歉意。 Ps:为了简洁起见,我使用了“指针”一词,但没有指定其类型。
我们用它来指示一个带有符号*
的指针。迭代该过程,我们获得“双”指针**
,“三重”指针***
,以及更一般地,“d维”指针(对于每个d正自然数)。创建一个d维指针
问题:给定这样一个d作为输入,将S定义为d维指针。
因为我几天前才开始研究动态结构,所以我很不幸地遇到了这个问题。 有没有人有建议/提示?
非常感谢您的提问,对于我可能过于基本的问题表示歉意。 Ps:为了简洁起见,我使用了“指针”一词,但没有指定其类型。
该问题具有在C语言的溶液,只要满足两个条件:
d
值是在编译时已知的,并且d
具有预先定义的限制,例如10您可以通过定义一系列的宏和“粘贴”的d
作为标记值解决这个问题:
#define D_PTR(d,T) D_PTR##d(T)
#define D_PTR0(T) T
#define D_PTR1(T) T*
#define D_PTR2(T) T**
#define D_PTR3(T) T***
...
#define D_PTR10(T) T**********
现在,你可以声明d
- 尺寸指针这样的:
D_PTR(5,int) ptr5 = NULL;
问题:给定这样一个d作为输入,将S定义为一个d维 指针。
如果不是具有任意数量的间接级别的指针,它可能在运行时在函数上表示N维数组。这可能是一个开始(未编译的,这完全忽略任何可能的调整问题):
void *allocateArray(unsigned int N, size_t elemSize, unsigned int *dimensions)
{
if (N == 1U)
{
return(malloc(elemSize * dimensions[ 0 ]))
}
void *array = malloc(sizeof(void *) * dimensions[ 0 ]);
for (unsigned ii = 0; ii < dimensions[ 0 ]; ii++)
{
array[ ii ] = allocateArray(N - 1, elemSize, &(dimensions[ 1 ]));
}
return(array);
}
请注意,这不是一种分配N维数组的一个非常有效的方式。
你可以这样调用它:
unsigned dims[] = { 5,7,8,9 };
unsigned d = sizeof(dims)/sizeof(dims[ 0 ]);
size_t elemSize = sizeof(double);
void *array = allocateArray(d, elemSize, dims);
一个可变参数的解决方案可能是可能的。
解引用数组需要类似的东西。这将返回元素的地址解引用:
void *dereferenceArray(void *array, unsigned int N,
size_t elemSize, unsigned int *element)
{
if (N == 1U)
{
char *tmp = array;
return(tmp + (elemSize * element[ 0 ]));
}
else
{
void **tmp = array;
return(dereferenceArray(tmp[ element[ 0 ] ],
N - 1, elemSize, &(element[ 1 ])));
}
}
它会在C更容易++,你可以提供一个[]
运营商的数组对象和巢他们建立N维数组。
基本上*
的数字表示达到变量的间接数。所以你必须创建d indirections。我认为这没有实际应用 - 这是一个休闲问题的答案。
C中的间接寻址是一个地址,一个指针。创建间接指的是创建和地址以获得可变数据(分配给类型T的变量的空间)。
p(d) -> p(d-1) -> ... -> p(1) -> variable
要动态创建这样的结构,则可以通过的malloc(与任何已知类型的替换T)做到这一点,以及 - 因为可能没有指定的*
动态的指针的数目 - 需要一些C黑客攻击。
所以,再次这不是推荐,是一个特别糟糕的设计,尤其是对于没有经验的C语言开发。目的是显示它可以动态地完成,无论和的值如何。
说T是双
int d = ...; // from input (d >= 1)
double variable;
double **S = malloc(sizeof(double *) * d); // array of pointers to pointer
S[d-1] = &variable; // last address points to target
int i;
for(i=d-2 ; i>=0 ; i--) S[i] = (double *)&S[i+1]; // previous address
// points to next location
没有方法来表示用C间接寻址的任意数量,所以S
只是一个**
满足编译器的要求,并且是铸造时必要的。
让我们尝试用d设置为和应用上面(比如T是一个双),其
double variable is at address 0100 (decimal), value 3.14
S address given by malloc at 1000
a pointer size being 4
a double size being 8
variable
v
[8 bytes double value 3.14]
^
0100
S
v
[1004][1008][1012][0100]
^ ^
1000 1012
现在的结构是否到位,如何使用/测试的算法?你可以创建一个返回类型T(双这里)功能,将S值和d,操作d间接性和返回变量
double getvariable(double **S, int d) {
while (--d > 0) S = (double **)*S; // d-1 iterations
return *(double *)*S;
}
尝一尝
printf("%lf\n", getvariable(S, d)); // 3.14
检验以上结构没有功能,d = = 4,您可以创建
double ****p = (double ****)*S;
printf("%lf\n", ****p); // 3.14
有三种不同的方法来解决这个问题:
您的d
是编译时常量。对于这种情况,dasblinkenlight has already given the solution。
的哈克-C的解决方案:只需使用强制取回指针类型:
double* dereferenceDLevels(double* pointer, int d) {
for(; d--;) pointer = *(double**)pointer;
return pointer;
}
我不推荐这种方法,虽然。它太脏了。
你实现你d
-level指针作为用户定义类型:
typedef struct nLevelPointer {
int n;
union {
nLevelPointer* pointer;
double value;
};
} nLevelPointer;
double nLevelPointer_dereference(nLevelPointer* me) {
for(int i = me->n; i--;) me = me->pointer;
return me->value;
}
我认为这种方法最干净,最灵活的一个。然而,它需要权衡大量的样板代码才能使其飞行。
您可以通过链接尽可能多的void **指针来创建d-indirection指针的运行时等价物。然后可以这样构建一个稀疏数组:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
printf("Call this passing d (dimensions), n (elements for each dim), u (used elements) as parameters\n");
return 0;
}
int d = atoi(argv[1]);
assert(d > 0);
int n = atoi(argv[2]);
assert(n > 0);
int u = atoi(argv[3]);
assert(u < n * d);
// Creating
void *root = malloc(sizeof(void *) * n);
memset(root, 0, sizeof(void *) * n);
srand(time(NULL));
int i, p, c;
void **cursor;
for (int c = 0; c < u; ++c)
{
cursor = root;
for (i = 0; i < d; ++i)
{
p = rand() % n;
if (cursor[p] == NULL)
{
cursor[p] = malloc(sizeof(void *) * n);
memset(cursor[p], 0, sizeof(void *) * n);
}
cursor = cursor[p];
}
p = rand() % n;
if (cursor[p] == NULL)
cursor[p] = "Hello";
else
--c;
}
// Traversing
struct SE
{
void * *s;
int p;
};
struct SE *stack = malloc(sizeof(struct SE) * (d + 1));
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
}
else if (cursor[p] != NULL)
{
if (i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
else
{
printf("root");
for (c = 0; c < i; ++c)
printf("[%d]->", stack[c].p);
printf("[%d]=\"%s\"\n", p, cursor[p]);
}
}
}
// Tearing down
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
free(cursor[p]);
}
else if (cursor[p] != NULL && i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
}
free(root);
free(stack);
return 0;
}
绝不要使用超过两级间接指针的指针,否则我会建议甚至不使用指针直到除非必要。 – haccks
听起来好像你想要一个d维数据结构,可能是一个带有查找函数的平面数组,而不是d级指针。你不能使间接程度(星号数)动态化。 –
@haccks - *永远不要使用超过两级间接指针的指针...... *你将如何创建一个可变大小的三维数组? –