程序员!
我完全沉没了双指针(指向指针)......这里有很多问题!
让我们从这个任务开始:我正在编写我的自定义版本的'calloc'func,它必须返回指向'n'大小'size'的内存元素的指针。这就是我发明的:
void **calloc1(int n, int size)
{
int i, j;
char *tmp, **p = NULL;
tmp = (char *) malloc1(n * size);
p = tmp;
for (i = 0; i < n; i++) {
p[i] = tmp;
for (j = 0; j < size; j++)
tmp++;
}
p = &p[0];
return (void **)p;
}
/* I entered n==4, size==3; real pointers are: p[0] == 0x804cfe0; p[1] == 0x804cfe3; p[2] == 0x804cfe6; ... */
因此,基本上我分配了n *个大小的字节,然后“分配”相同“大小”的指针数组到相应的起始位置。 让我们输入n = 4和size = 3;这意味着p [0]指向tmp [0],p [1]指向tmp [3],p [2]指向tmp [6],依此类推。 在GDB中,我几乎在每一步之后跟踪指针值。
然后,在'main'中我声明了一个双指针,并将它“附加”到从我的'calloc'收到的缓冲区中:
int main (short argc, char **argv)
{
char **space;
space = (char **) calloc1(n, size); /* removing '(char**)' here does not have effect */
/* at this stage pointers seems to be correctly "located": 'space' == 'space[0]' == 0x804cfe0; 'space[1]' == 0x804cfe3; 'space[2]' == 0x804cfe6; ... */
1)这是第一个问题:'main()'(或者我将传递** p副本的任何其他函数)如何知道指针算术的大小?例如,'main()'如何知道如果我向'space'添加'1'(或者只是递增一次),它应该指向它的第二个指针(在'calloc'中它是p [1]),这(在这种特殊情况下)是第一个指针(p [0])的3个字符? 此外,如果我在“alloc”数组中创建指向“可变长度”字符串的指针(例如,p [0]指向tmp [0],p [1]指向tmp [7],p [2]指向tmp [11]等),任何其他函数如何知道它应该将“上”指针增加4和7“字符”增加?
好吧,我们继续前进,我尝试将一些字符放入获得的缓冲区:
int i = 0, j = 0, n, size;
char nn, ssize, c, temp[3];
printf ("Enter number/size \n");
sc = scanf ("%c/%c", &nn, &ssize);
n = nn - '0'; /* n==4 */
size = ssize - '0'; /* size==3 */
printf ("Enter a 'number' of words\n");
while (j < n) {
for (i = 0; (c = getchar()) != EOF && i < size; i++)
*(*space)++ = c;
(*space)--; /* this line is unneccesary; if I remove it - nothing changes */
++j;
++space;
}
2)以下是第一个问题的证据:实际上,当我在这里增加“空间”时,它不会移动3而是移动4个字符(在第一个'++'之后它是0x804cfe4,在第二个0x804cfe8之后)。为什么?有'浮动'型尺寸的连接吗? 在第一次这样的递增之后,'* space'指向0x804cfe6 ...我不认为它是正确的。
我尝试过另一种方式 - 引用'space',不是指针而是数组:
....
while (j < n) {
for (i = 0; (c = getchar()) != EOF && i < size; i++)
*space[j]++ = c;
space[j]--;
++j;
}
3)在这种情况下,指针似乎没问题 - 例如space [1] == 0x804cfe3,space [2] == 0x804cfe6。问题是,当这个循环以j == 2运行时,'space [0]'的值以某种方式从0x804cfe2(移动两次 - ok)变为类似0x6a04cfe2(超出界限)。什么h .. ???
4)而且,地址有一些奇怪的行为。我也尝试过不直接将字符写入**空格,而是使用字符串复制功能:
char i, temp[3];
...
while (j < n) {
for (i = 0; (c = getchar()) != EOF && i < size; i++)
temp[i] = c;
strncpy1 (space[j],temp,3);
++j;
}
.....
void strncpy1 (char *s, char *t, int k)
{
while (--k > 0) {
*s = *t;
s++; t++;
}
}
内部复制功能,复制和递增显示GDB正确。但是从'strncpy1'返回后,space [j]从0x804cfe0变为0x804000a。被调用的函数如何能够影响父母的(外部)指针?
最后,什么类型的指针指向char指针?它有多大?
答案 0 :(得分:1)
我相信你的指针系统大小是4,因为你正在使用一个指向指针的指针,然后将它包含在内,所以它将4个字节添加到当前位置以到达其类型的下一个指针(char **)。
注意:您没有将指针递增到char,而是将指针递增到指针。
现在再次,如果我谈论你的第二个问题,功能将如何知道在哪里增加4和哪里7,所以它与功能无关。因为指针的数组确实存在于连续位置上的指针地址(它们不是指针的值,我说的是保存在指针数组中的指针)所以它只会将指针递增1并将到达下一个指针它的类型天气是P [0]或P [4]或p [7] ..
答案 1 :(得分:1)
您遇到的最大问题是您对指针和数据使用相同的内存位置。这就是为什么你会看到这种奇怪的行为。
您只分配一个缓冲区,然后使用此缓冲区将指针包含到同一缓冲区中。当然,当您修改内容时,您的指针会发生变化。您必须具有单独的内存位置:一个用于数据,另一个用于指向该数据的指针。
如果你真的想这样做,你可以这样做:
void **calloc1(int n, int size)
{
int i, j;
char *tmp, **p = NULL;
tmp = (char *) malloc1(n * size);
p = (char**) malloc1(n * sizeof(char*));
...
注意:这样你自然需要两个调用来释放内存,而你可能无法知道第二个是什么,因为用户可以改变指针。所以更好的方法是将分配合并为一个:
void **calloc1(int n, int size)
{
int i, j;
char *tmp, **p = NULL;
p = (char**) malloc1(n * size + n * sizeof(char*));
tmp = (char *) (p + n);
...
这种方式有一个p指向的分配,但指针会有与实际项目分开的内存。
至于其他问题:
1)怎样才能#(主)()&#39;知道指针算术的大小吗?
指针始终具有固定大小。他们指点,他们不关心他们指向的是什么。 sizeof(char *)== sizeof(int *)== sizeof(yourcoolstruct *)
2)当我增加&#39;空间&#39;在这里,它不是移动3而是移动4个字符(在第一个&#39; ++&#39;它是0x804cfe4,在第二个0x804cfe8之后)。为什么?是否与“&#39; -type size”有某种联系?
因为在你的系统sizeof(指针)== 4,所以每个指针需要4个字节。在32位环境中正常,与浮点数,整数或任何东西无关。
3)当此循环以j == 2运行时,空间[0]&#39;的值为某种程度上从0x804cfe2(移动两次 - 确定)变为类似0x6a04cfe2(超出界限)。什么h .. ???
因为对指针和数据使用相同的内存。你写的是&#39; j&#39; (0x6A,十六进制)到空间[1] [0],它指向分配的第四个字节。哪个也是space [0]指针的最重要的字节,所以它就变成了。