C - 初始化时未修改位域

C - Bit Fields not modified when init

我想知道为什么在我的 malloc 之后所有修改都不起作用。 这是我用来说明这一点的代码:

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

struct Age {
   unsigned int age : 16;
   unsigned int two : 2;
   unsigned int notToBeInitialed: 2;
};

int init(struct Age * p){
 p = (struct Age *) malloc( sizeof(struct Age) );
 p->age = 5;
 return 0;
}

int change(struct Age * p){
   p->age = 99; 
}

int getValue(struct Age * p){
  return p->age;    
}

int main(void) {
    struct Age test;
    init(&test);
    printf( "Age.age : %d\n", getValue(&test) ); // gives me 0 , expected 5
    change(&test);
    printf( "Age.age : %d\n", getValue(&test) ); // gives me 99 
    return 0;
}

我做错了什么?

感谢您的帮助。

来源:http://www.tutorialspoint.com/cprogramming/c_bit_fields.htm 艾德奥内 : https://ideone.com/O59tqZ

您对 malloc 的调用将覆盖收到的参数。所以初始化转到那个新对象,然后在函数 returns.

时泄漏

看来你混淆了初始化和分配。

init 函数中删除 malloc

那么你可以简单地分两步分配 init。一个好的成语是

struct Age* init(struct Age * p){
 if (p) {
   p->age = 5;
 }
 return p;
}

....

struct Age* testp = init(malloc(sizeof *testp));

顺便说一句,malloc 的 return 不能也不应该在 C 中转换。

这段代码似乎有一些误解。首先,您在 main 函数内的堆栈上分配一个 Age 结构。然后将指向 this 的指针传递给 init 函数。到目前为止,一切都很好。但是您随后在 init 函数内为新的 Age 结构分配内存。您修改了这个新版本的内容,但指向它的指针仅存储在 'init' 函数内的局部 'p' 变量中,它不会以任何方式传回。当您打印内容时,您打印的是堆栈分配的 Age 结构,而不是您所做更改的使用 malloc 分配的结构。

如果您想将对堆栈分配结构的引用传递给 init,并让 init 修改它,那么您应该完全删除 malloc 行。

如果你想让你的 init 函数分配一个新的 Age 结构,那么它需要将 'struct Age** p' 作为它的参数,以允许它传递一个 'struct Age* p',在下面方式:



    void init(struct Age** p){
        *p = (struct Age *)malloc( sizeof(struct Age) );
        (*p)->age = 5;
    }

    int main(void) {
        struct Age* test;
        init(&test);
        printf( "Age.age : %d\n", test->age );
    }

我还将初始化函数的 return 类型更改为 void,因为 return 值似乎没有任何作用。您可能还应该将 'change' 函数的 return 类型更改为 void,因为它似乎 return 没有任何值。

你显然误解了自动存储和动态内存分配的区别。

局部变量

struct Age test

使用自动存储定义一个 Age 对象。 您无需执行任何其他操作,此对象已存在并且现在可用。声明此类对象的唯一缺点是它们存在于整个声明范围内。 您不应该在此对象上调用 init(至少不是 malloc 部分),因为它已经初始化,只需使用 test.age.

设置它的值

以下将按预期工作:

int main(void) {
    struct Age test;
    test.age = 5;
    printf( "Age.age : %d\n", getValue(&test) );
    change(&test);
    printf( "Age.age : %d\n", getValue(&test) );
    return 0;
}

动态内存分配

另一方面,以下内容:

p = (struct Age *) malloc( sizeof(struct Age) );

使用动态内存分配。 分配新内存,然后返回一个指针给你。 在这种情况下,您决定使用此内存来保存 Age 对象。

int init(struct Age ** p){
    *p = (struct Age *) malloc( sizeof(struct Age) );
    (*p)->age = 5;
}

int main(void) {
    struct Age * test;
    init(&test)
    printf( "Age.age : %d\n", getValue(test) );
    change(test);
    printf( "Age.age : %d\n", getValue(test) );
    return 0;
}

总结

这两种方法是互斥的。当您创建局部变量时,没有必要为其分配额外的内存。

您正在按值将指针传递给函数 init。这意味着该函数对该指针的副本进行操作。在这种情况下,您正在为其分配一个新地址,但原始指针不会更改。如果要为指针分配一个新值,该值将在函数 return 之后保留,您必须将指针的地址(指向指针的指针)传递给函数。

但在您的示例中,在 main 中,您在堆栈上实例化 struct Age。您不能通过在堆上分配内存(使用 malloc)来更改其地址(位置)。您所能做的就是在堆上创建一个全新的对象(这就是您在 init 中所做的)。但是你在那个函数中有内存泄漏,因为 malloc-ed 内存永远不会 freed.