程序员!
我完全沉迷于双指针(指针对指针)......这里有很多问题!
让我们从这个任务开始:我正在编写自定义版本的“calloc”函数,它必须返回指向“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*size 个字节,然后将相等“大小”的指针数组“分配”到相应的起始位置。让我们输入 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()' 是如何知道如果我将 '1' 添加到 'space' (或简单地增加一次),它应该指向它的第二个指针(在 '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...我认为它不正确。
我尝试了另一种方式 - 引用“空间”,而不是指针而是数组:
....
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(超出范围)。什么。。???
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 之类的东西。被调用函数怎么可能影响父母的(外部)指针?
那么最后,指针到字符指针是什么类型的?它有什么尺寸?