【问题标题】:C structure initialization - interestingC 结构初始化 - 有趣
【发布时间】:2014-09-01 11:30:59
【问题描述】:

我有一个 C 程序,它初始化两个结构并尝试打印它们的值。请看下面的代码。

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

typedef struct node{
    int data;
    struct node * next;
}node_t;

typedef struct bstNode{
    int data;
    struct bstNode* right;
    struct bstNode* left;
}bstNode_t;

main(){
    struct bstNode* rootptr = malloc(sizeof(struct bstNode));

    printf("\n*rootptr  %x\n",*rootptr);
    printf("rootptr = %x\n",rootptr);

    rootptr->data = 8;
    rootptr->left = NULL;

    printf("\n*rootptr  %x\n",*rootptr);
    printf("rootptr = %x\n",rootptr);


    node_t* tmp = (node_t*) malloc(sizeof(node_t));

    printf("\n*tmp = %x",*tmp);
    printf("\n tmp = %x\n",tmp);

    tmp->data = 9;
    tmp->next = NULL;

    printf("\n*tmp = %x",*tmp);
    printf("\n tmp = %x\n",tmp);
    printf("\n ptr size = %x\n",sizeof(int));

}

程序的输出是

*rootptr  20fe1
rootptr = 4a78010

*rootptr  4691e000
rootptr = 4a78010

*tmp = 0
 tmp = 4a78030

*tmp = 9
 tmp = 4a78030

 ptr size = 4

令我惊讶的是,*rootptr 的值与 *tmp 不同。在将值分配给变量之前和之后。为什么会这样? 当 *tmp 可以将值打印为 9。为什么 *rootptr 不打印为 8 ? 这里数据是两个结构中的第一个值。所以指针(结构)处的值应该打印第一个数据的值,对吧?

【问题讨论】:

  • 请正确格式化您的代码。
  • 不要使用%x打印数据指针,而是使用%p。你不能用%x类似地打印struct node对象。打印未初始化值的结果定义不明确,可能是任何垃圾,包括但不限于 0。这里您打印的是第一个成员,但它可能会在其他目标上打印其他内容。
  • printf("\n*rootptr %x\n",*rootptr); 是什么意思?您是否要打印数据所持有的值?
  • 我们已经帮助您格式化代码。快完成了。请花点时间缩进main 的后半部分以匹配其余缩进。
  • 这里我正在查看我可以将 *tmp 打印为 9 的问题。但 *rootptr 作为一些垃圾。我预计它是 8。为什么会这样?

标签: c memory malloc structure


【解决方案1】:

您不能使用

打印自定义结构的值
printf("\n*rootptr  %x\n",*rootptr);
printf("\n*tmp = %x",*tmp);

您应该编写一个自定义函数并调用它来打印 BST 和节点指针。 例如:

int print_node(node_t *nd)
{
  if(nd == 0) return printf("<null>");
  else return printf("[data = %d, next = %p]", nd->data, nd->next);
}

稍后将printf("\n*rootptr %x\n",*rootptr); 替换为

printf("\n*rootptr  ");
print_node(rootptr);
printf("\n");

同样,您也可以编写自定义函数来打印 BST 节点。

关于 printf %x 说明符,来自手册页

o, u, x, X
unsigned int argument 被转换为无符号 八进制 (o)、无符号十进制 (u) 或无符号十六进制(x 和 X) 符号。字母 abcdef 用于 x 转换;字母 ABCDEF 用于 X 转换。精度(如果有)给出了必须出现的最小位数;如果 转换后的值需要更少的数字,它被填充在 留下零。默认精度为 1。当使用显式精度 0 打印 0 时,输出为空。

如果参数不是无符号整数,您可能会得到奇怪的结果。

【讨论】:

    【解决方案2】:

    当您尝试打印结构成员值时,您不应使用* 运算符来执行此操作。相反,您应该根据其类型使用 .-&gt; 运算符来执行此操作!

    试试这个改变-

    #include<stdio.h>
    #include<stdlib.h>
    typedef struct node{
            int data;
            struct node * next;
    }node_t;
    
    typedef struct bstNode{
            int data;
            struct bstNode* right;
            struct bstNode* left;
    }bstNode_t;
    
    int main(){
    
            struct bstNode* rootptr = malloc(sizeof(struct bstNode)); // where rootptr is structure pointer. so you need do use -> operator to access ins members
    
            printf("\nrootptr->data  %d\n",rootptr->data); // Fix 1.
            printf("rootptr = %p\n",rootptr); // use %p to print addresses
    
            rootptr->data = 8;
            rootptr->left = NULL;
    
            printf("\nrootptr->data  %d\n",rootptr->data); // Fix 2.
            printf("rootptr = %p\n",rootptr);
    
            node_t* tmp = (node_t*) malloc(sizeof(node_t));
    
            printf("\ntmp->data = %d",tmp->data); // Fix 3.
            printf("\n tmp = %p\n",tmp);
    
            tmp->data = 9;
            tmp->next = NULL;
    
            printf("\ntmp->data = %d",tmp->data); // Fix 4.
            printf("\n tmp = %p\n",tmp);
    
            printf("\n ptr size = %x\n",sizeof(int));
    
            return 0;
    }
    

    输出-

    rootptr->data  0
    rootptr = 0x966a008
    
    rootptr->data  8
    rootptr = 0x966a008
    
    tmp->data = 0
     tmp = 0x966a018
    
    tmp->data = 9
     tmp = 0x966a018
    
     ptr size = 4
    

    【讨论】:

    • 这个我明白。但是我想知道的是,为什么会有区别,当*tmp可以打印数据为9,为什么*rootptr不能打印8?
    【解决方案3】:

    输出是正确的,不知何故你得到了这个结果....让我解释一下。

    当你调用“malloc”时,内存是分配给你的,但它没有被初始化,所以基本上如果之前使用过内存,它只是“脏”了一些过去的值。您必须始终初始化您的值,否则指向的内存内容将是脏的。

    现在,让我们看看你对编译器的要求:

    printf("\n*rootptr  %x\n",*rootptr);
    

    您基本上要求打印一个指针 (%x),但传递的参数是一个取消引用的指针 (*rootptr)。在这种情况下,printf 会收到 4 个字节的解引用指针:前两个字节是 rootptr-&gt;data 的值,后两个字节是 rootptr-&gt;left 的值

    由于 rootptr->data 和 rootptr->left 的值(这是您打印的)都随时间变化,因为您设置了一些值,因此 *rootptr 的输出随时间变化。

    同样适用于tmp

    在第二种情况下,你问

    printf("rootptr = %x\n",rootptr);
    

    所以你要求编译器打印指针的地址。这是正确的,你可以看到它不会在你的输出中改变

    底线:如果您的意图是打印整个结构,您应该这样做:

    printf("\nrootptr value %d,%x,%x\n",rootptr->data, rootptr->left, rootptr->right);
    

    除非您完全了解其结构,否则切勿打印取消引用的指针

    【讨论】:

    • 打印取消引用的指针没有任何问题。另一方面打印结构......我认为没有格式说明符!
    • %x 用于打印无符号整数。试图打印一个导致未定义行为的指针。
    • 这里我正在查看可以将 *tmp 打印为 9 的问题。但 *rootptr 是一些垃圾。我预计它是 8。为什么会这样?
    猜你喜欢
    • 2012-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多