我是关于指针的新手,有人能解释一下下面代码中输出的不同吗?在下面的代码中,我将一些值分配给3d指针。我在任务后打印出来。然后再将它们打印在不同的块中。为什么输出会有所不同?
#include<stdio.h>
#define row 5
#define rw 3
#define col 10
char ***ptr,sh[10];
int i,j,k;
int main()
{
ptr=(char *)malloc(row*sizeof(char *));
for(i=0;i<row;i++)
{
*(ptr+i)=(char *)malloc(rw*sizeof(char *));
printf("\t:\n");
for(j=0;j<rw;j++)
{
*(*(ptr+i)+j)=(char *)malloc(col*sizeof(char *));
if(i==0 && j==0)
{
// *(*(ptr+row)+rw)="kabul";
**ptr="zapac";
}
else
{
sh[0]=i+48;
sh[1]=',';
sh[2]=j+48;
sh[3]='\0';
*(*(ptr+i)+j)=sh;
}
printf("\t%d%d = %s\n",i,j,ptr[i][j]);
}
printf("\n");
}
for(i=0;i<row;i++)
{
for(j=0;j<rw;j++)
{
printf("\t%d%d %s\n",i,j,ptr[i][j]);
}
printf("\n");
}
return 0;
}
输出结果为:
:
00 = zapac
01 = 0,1
02 = 0,2
:
10 = 1,0
11 = 1,1
12 = 1,2
:
20 = 2,0
21 = 2,1
22 = 2,2
:
30 = 3,0
31 = 3,1
32 = 3,2
:
40 = 4,0
41 = 4,1
42 = 4,2
我的问题是,为什么以下输出不同意上述内容?
00 zapac
01 4,2
02 4,2
10 4,2
11 4,2
12 4,2
20 4,2
21 4,2
22 4,2
30 4,2
31 4,2
32 4,2
40 4,2
41 4,2
42 4,2
答案 0 :(得分:0)
因为 sh [10] 是全局定义的,而第一个循环是打印此数组的当前值 - 不保留此数组的内容 - 每次迭代都会更改。对于第二个循环,您将打印在第一个循环期间(即在最后一次迭代中)写入的最后一个值。
你最好在第一个循环的每次迭代中分配:
for(j=0;j<rw;j++)
{
*(*(ptr+i)+j)=(char *)malloc(col*sizeof(char *));
char* psh = (char*)malloc(10*sizeof(char));
if(i==0 && j==0)
{
strcpy(psh, "zapac");
}
else
{
psh[0]=i+48;
psh[1]=',';
psh[2]=j+48;
psh[3]='\0';
*(*(ptr+i)+j)=psh;
}
PS要注意硬编码的10-char大小,可能需要额外的检查/断言。
答案 1 :(得分:0)
您获得输出的原因是您的*(*(ptr+i)+j) = sh
将所有char *
(除了第一个,您已特别处理过的)设置为相同的值,即sh
中数组数据的地址。只有sh
的一个副本,其数组数据的一个副本;您的所有char *
指向该单个副本。当您稍后打印出这些值时,您只需通过不同的指针一遍又一遍地打印相同的数据副本 - 这样您就可以在上次修改它时将所有内容放入sh
而不是设置指针时它在里面是什么。
您可能希望每个char *
获取数组的新副本而不是仅指向sh
,但如果这是您想要的,则必须自己复制数据。
所以...如果你替换这一行:
*(*(ptr+i)+j)=sh;
有类似的东西:
*(*(ptr+i)+j)=malloc(sizeof(sh));
strcpy( *(*(ptr+i)+j), sh );
或
ptr[i][j] = calloc(1,sizeof(sh));
strcpy( ptr[i][j], sh );
您将得到您的期望,因为每个char *
将指向复制时sh
中的字符串的新副本。你需要记住以后将它们与你malloc()
编辑的所有内容一起释放。
您的大多数malloc()
行也不正确,但由于char *
,char **
和char ***
可能在您的系统上大小相同,因此无论如何都有效。
ptr=(char *)malloc(row*sizeof(char *));
应该是
ptr = (char ***)malloc(row*sizeof(char **));
因为你正在分配一个char **
数组(指向char
的指针),这个数组是通过char ***
(指向指针指向{{}的指针访问的。 1}} 的)。同样地:
char
应该是
*(ptr+i)=(char *)malloc(rw*sizeof(char *));
或
*(ptr+i)=(char **)malloc(rw*sizeof(char *));
分配通过ptr[i] = (char **)malloc(rw * sizeof(char *));
(指向<{1}} 的指针)访问的char *
(指向char
的指针)数组。
char **
次调用前的演员阵容实际上是可选的 - char
的{{1}}结果将被转换为您分配给它的任何指针类型。但是,在这种情况下,使用强制转换应该让编译器警告您类型错误。
答案 2 :(得分:0)
@Dmitri对于你所看到的症状的原因是正确的,但你的代码中还有其他问题,有些是严重的,有些则不那么严重。
这是您程序的修改版本。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROW 5
#define RW 3
#define COL 10
int main(void)
{
char ***ptr;
char sh[10];
ptr = malloc(ROW * sizeof *ptr);
for (int i = 0; i < ROW; i++)
{
ptr[i] = malloc(RW * sizeof *(ptr[i]));
printf("\t:\n");
for (int j = 0; j < RW; j++)
{
ptr[i][j] = malloc(COL * sizeof *(ptr[i][j]));
if (i==0 && j==0)
{
// *(*(ptr+ROW)+RW) = "kabul";
ptr[i][j] = "zapac";
}
else
{
sh[0] = '0' + i;
sh[1] = ',';
sh[2] = '0' + j;
sh[3] = '\0';
// ptr[i][j] = sh;
strcpy(ptr[i][j], sh);
}
// printf("\t%d%d = %s\n", i, j, ptr[i][j]);
printf("\tptr[%d][%d] = \"%s\"\n", i, j, ptr[i][j]);
}
printf("\n");
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < RW; j++)
{
// printf("\t%d%d %s\n", i, j, ptr[i][j]);
printf("\tptr[%d][%d] = \"%s\"\n", i, j, ptr[i][j]);
}
printf("\n");
}
return 0;
}
我所做的改变是:
添加#include <stdlib.h>
以获取malloc()
的声明。这不是可选的(虽然编译器可能会让你省略它)。如果没有#include <stdlib.h>
,则前C99编译器会假设malloc()
返回int
;这会导致未定义的行为。这意味着可能发生任意不好的事情 - 或者它可能恰好在某些系统上发挥作用。
按照通常使用全大写字母名称的惯例。
添加一些空格(我发现它使代码更易读,特别是在每个逗号后面和大多数操作符后面都有空格)。
将变量设为局部变量而不是全局变量。
在各自的循环中声明循环控制变量。这是C99特有的功能,但您的编译器可能支持它。 (对于gcc,请使用gcc -std=c99
。)
修复malloc()
次调用,以根据指针指向的大小计算大小。
使用索引运算符而不是显式指针算法。一般来说,x[y]
表示*(x+y)
,因此,例如,*(*(ptr+i)+j)
可以简单地写为ptr[i][j]
。
使用strcpy()
将sh
中存储的字符串复制到the string pointed to by
ptr [i] [j]`中,而不仅仅是复制指针。 (这解决了Dmitri已经找到的问题;你应该接受他的答案,因为他先提到了。)
修改printf
来电产生的输出,以便更容易看到发生了什么。