需要c指针解释

需要c指针解释,c,pointers,C,Pointers,关于指针,我是新手,有人能解释一下下面代码中输出的不同之处吗?在下面的代码中,我给一个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 *));

关于指针,我是新手,有人能解释一下下面代码中输出的不同之处吗?在下面的代码中,我给一个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 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

因为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;
            }

for(j=0;j获得输出的原因是您的
*(*(ptr+i)+j)=sh
正在设置所有的
char*
s(第一个除外,您专门处理过)同一个值,这是
sh
中数组数据的地址。只有一个
sh
副本,它的数组数据的一个副本;所有
char*
s都指向该单个副本。以后打印值时,您只是通过指向它的不同指针反复打印相同的数据副本,所以y您将获得上次修改时放入的内容,而不是设置指针时放入的内容

您可能希望每个
char*
都获得数组的新副本,而不是仅仅指向
sh
,但是如果这是您想要的,您必须自己复制数据

所以…如果您替换这一行:

*(*(ptr+i)+j)=sh;
比如:

*(*(ptr+i)+j)=malloc(sizeof(sh));
strcpy( *(*(ptr+i)+j), sh );

您将得到您期望的结果,因为每个
char*
将指向复制时
sh
中的字符串的新副本。不过,您需要记住稍后释放它们以及
malloc()
ed中的所有内容

大多数
malloc()
行也不正确,但由于
char*
char**
char***
在系统上可能大小相同,因此它仍然可以工作

ptr=(char *)malloc(row*sizeof(char *));
应该是

ptr = (char ***)malloc(row*sizeof(char **));
*(ptr+i)=(char **)malloc(rw*sizeof(char *));
由于您正在分配一个
char**
(指针指向
char
)数组,可通过
char***
(指针指向
char
)访问该数组。同样:

*(ptr+i)=(char *)malloc(rw*sizeof(char *));
应该是

ptr = (char ***)malloc(row*sizeof(char **));
*(ptr+i)=(char **)malloc(rw*sizeof(char *));

分配通过
char**
(指向
char
的指针)访问的
char*
(指向
char
的指针)数组


malloc()调用前面的强制转换实际上是可选的--
malloc()
void*
结果将被转换为您分配给它的任何指针类型。但是,在这种情况下,强制转换应该会使编译器警告您类型错误。

@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;
}
#包括
#包括
#包括
#定义第5行
#定义RW3
#定义第10列
内部主(空)
{
字符***ptr;
char-sh[10];
ptr=malloc(行*sizeof*ptr);
对于(int i=0;i
我所做的更改是:

  • 添加
    #include
    以获取
    malloc()的声明
    。这不是可选的(尽管编译器可能允许您忽略它)。如果没有
    #include
    ,C99之前的编译器将假定
    malloc()
    返回一个
    int
    ;这会导致未定义的行为。这意味着可能会发生任意不好的事情,或者可能会发生在某些系统上

  • 遵循宏使用所有caps名称的常规

  • 添加一些空格(我发现它使代码更清晰,尤其是在每个逗号后面和大多数运算符周围都有空格)

  • 使变量成为局部变量而不是全局变量

  • 在各自的循环中声明循环控制变量。这是C99特有的功能,但您的编译器可能支持它。(对于gcc,请使用
    gcc-std=C99

  • 修复
    malloc()
    调用,根据指针指向的大小计算大小

  • 使用索引运算符而不是显式指针算法。通常,
    x[y]
    表示
    *(x+y)
    ,因此,例如,
    *(*(ptr+i)+j)
    可以简单地写成
    ptr[i][j]

  • 使用
    strcpy()
    将存储在
    sh
    中的字符串复制到
    ptr[i][j]指向的字符串中,而不仅仅是复制指针。(这解决了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;
    }