【问题标题】:Initialization function (i.e. "constructor") for struct, why are variables not being initialized properly?结构的初始化函数(即“构造函数”),为什么没有正确初始化变量?
【发布时间】:2015-10-18 20:46:59
【问题描述】:

我有一个名为“FooStruct”的未命名结构,我为它编写了一个函数来初始化它的所有变量并负责动态内存分配。

我尝试运行此代码,但它没有产生我期望的结果。由于某种原因,变量在函数内部被正确初始化,但是一旦退出块,它们就会再次改变。

我正在进行的一个项目要求我只使用未命名的结构。为什么会这样?

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

typedef struct {
    int fooPrimitive;
} FooStruct;

void FooStructInit(FooStruct * ptr, int num) {
    ptr = (FooStruct*)malloc(sizeof(FooStruct));
    ptr -> fooPrimitive = num;

    // Expected output: 5
    // Actual output: 5
    printf("ptr -> fooPrimitive: %d\n", (ptr -> fooPrimitive));
}

int main() {
    FooStruct * ptr;
    FooStructInit(ptr, 5);

    // Expected output: 5
    // Actual output: some random number
    printf("FooStruct -> fooPrimitive: %d\n", (ptr -> fooPrimitive));
}

【问题讨论】:

  • 您不应在箭头-&gt; 或点. 运算符周围使用空格。它们结合得非常紧密;这应该通过不包括它们周围的任何空间来直观地显示。 (是的,就语法而言,空格很好;标记之间的任何位置都允许有空格,因此您可以将每个标记写在自己的行上。为了便于阅读,不要在箭头或点周围包含空格。)
  • 感谢您告诉我这一点,尽管他们并没有真正消除问题。
  • YW:这就是为什么它是评论,而不是答案。

标签: c struct initialization


【解决方案1】:

C只有传值语义,所以当你将指针传递给函数时,指针的原始值并没有改变,只是在函数中改变了本地副本。

解决这个问题的方法是将指针传递给指针,以便您可以更改原始内存位置的值。

void FooStructInit(FooStruct **ptr, int num) {
    *ptr = malloc(sizeof(FooStruct));
    ...
}

int main(void) {
    FooStruct * ptr;
    FooStructInit(&ptr, 5); /* get the address of the pointer */
    ...
}

【讨论】:

  • 在我的函数中仅使用 FooStruct * ptr 参数是否 100% 不可能?
  • @JohnH 不,这是不可能的。该函数只能修改其本地副本。
  • @JohnH:是的,仅使用 FooStruct *ptr 参数是 100% 不可能的。您可以不使用参数并返回分配的结构;那将是合法的。或者您可以让调用代码进行内存分配,并简单地让构造函数初始化先前分配的存储中的数据。这就是 C++ 构造函数的工作方式。好处是可以接着构造这种类型的局部变量和全局变量;您不会强迫人们使用动态分配的内存。
【解决方案2】:

当您将ptr 传递给FooStructInit 时,它被复制,然后此副本被分配malloc 的返回值。这称为按值传递。相反,传递一个指向 ptr 的指针来实际写入 ptr 而不仅仅是传递的参数:

void FooStructInit(FooStruct** ptr, int num) {
    *ptr = malloc(sizeof(FooStruct));
    (*ptr)->fooPrimitive = num;

    // Expected output: 5
    // Actual output: 5
    printf("(*ptr)->fooPrimitive: %d\n", ((*ptr)->fooPrimitive));
}

int main() {
    FooStruct* ptr;
    FooStructInit(&ptr, 5);

    // Expected output: 5
    // Actual output: 5
    printf("FooStruct->fooPrimitive: %d\n", (ptr->fooPrimitive));
}

注意事项:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 2020-09-27
    • 2015-02-19
    • 1970-01-01
    相关资源
    最近更新 更多