我們用它來指示一個帶有符號*
的指針。迭代該過程,我們獲得「雙」指針**
,「三重」指針***
,以及更一般地,「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 - *永遠不要使用超過兩級間接指針的指針...... *你將如何創建一個可變大小的三維數組? –