不同的输出用于不同数量的printf调用

时间:2019-01-21 13:58:07

标签: c struct printf malloc nan

我是C语言的新手,我的代码有一个奇怪的问题。

我正在尝试创建struct的数组作为struct另一个数组的一部分。

printf函数的数量不同时,我将获得不同的输出。我有两种情况,一种是正确的,但另一种是不正确的。

我不明白为什么简单地调用一个额外的printf就会改变结果。

这是我的代码,结果不正确,在这里我得到“ x velocity = -nan”

#include<stdlib.h>
#include<stdio.h>

struct vect3d1
{
    double *x,*y,*z;
};

struct block
{ 
   int ibl;
   struct vect3d1 *velocity;
};

void create_time(struct block *blocks,int Nsteps,int nb);


int main()
{

struct block *blocks;
int nb,i,t,Nsteps;
Nsteps=30;
nb=3;
blocks=calloc(nb, sizeof(struct block));
for (i=0;i<nb;i++){
        for(t=0;t<Nsteps;t++){

blocks[i].velocity=(struct vect3d1 *)malloc(Nsteps*sizeof(struct vect3d1));
blocks[i].velocity[t].x=NULL;
blocks[i].velocity[t].y=NULL;
blocks[i].velocity[t].z=NULL;

}
}

create_time(blocks,Nsteps,nb);

free(blocks);
}

void create_time(struct block *blocks,int Nsteps,int nb){

int i,t;
double u;

for (i=0;i<nb;i++){
    for(t=0;t<Nsteps;t++){
        u=0.5+t;
        blocks[i].velocity[t].x=&u;
//          printf("u %lf \n",u);
        printf("velocity x=%lf \n",blocks[i].velocity[t].x);

}
}


}

您会注意到函数create_time中的一行已被注释,当未对其注释时,结果是正确的。

为澄清起见,函数create_time是否为:

void create_time(struct block *blocks,int Nsteps,int nb){

int i,t;
double u;

for (i=0;i<nb;i++){
    for(t=0;t<Nsteps;t++){
        u=0.5+t;
        blocks[i].velocity[t].x=&u;
//          printf("u %lf \n",u);
        printf("velocity x=%lf \n",blocks[i].velocity[t].x);

}
}


}

我获得了:

"velocity x=-nan"

函数为:

void create_time(struct block *blocks,int Nsteps,int nb){

int i,t;
double u;

for (i=0;i<nb;i++){
    for(t=0;t<Nsteps;t++){
        u=0.5+t;
        blocks[i].velocity[t].x=&u;
            printf("u %lf \n",u);
        printf("velocity x=%lf \n",blocks[i].velocity[t].x);

}
}


}

我获得:

"u 0.5"

"velocity x=0.5"
...

,依此类推。

我已经添加了该行,只是为了验证变量u,然后我意识到,将其添加到printf的输出中已更改。

会发生什么?为什么printf的输出被更改?

1 个答案:

答案 0 :(得分:2)

这里

  printf("velocity x=%lf \n",blocks[i].velocity[t].x);

尽管期望使用double,但是您不会传递double而是指向double的指针。这调用了臭名昭著的未定义行为。不要这样做。

我也不知道为什么编译器没有警告您。您可能想提高编译器的减弱水平。对于GCC,在编译时添加选项-Wall -Wextra -pedantic

要解决此问题,将其更改为

  printf("velocity x=%lf \n", *blocks[i].velocity[t].x);

所以回答您的问题:

  

会发生什么?为什么更改printf的输出?

欢迎来到不确定行为的神秘世界。 ;)


除此之外,请注意此行

  blocks[i].velocity[t].x=&u;

是危险的,因为您将变量 local 的地址分配给该函数的指针,该指针很可能在离开函数后才被使用。

离开该功能后,它不会再指向有效内存。

取消引用它会调用未定义的行为,请注意。


最后一个友好的注释:请您自己和您的编码专家一起帮忙阅读您的代码,并正确缩进代码。这是免费调试。我有一个强烈的印象,this bug是由于所示代码的混乱缩进所致。