首页 > 解决方案 > 在 C 中声明指针的方法

问题描述

我学习 C 语言才不到一个星期(借助我对 C++ 和其他语言的了解),我对指针及其声明方式感到困惑。

下面,我使用了一个名为Object的简单结构:

struct Object { int id; }; 

以下用于创建指针的方法是否以不同的方式做同样的事情,或者没有?

struct  Object obj1 = { .id = 1 };
struct  Object* obj1_p = &obj1; // method 1 of getting a pointer

// The same, just in a compound literal?
struct  Object* obj2_p = &(struct Object){ .id = 1 }; // method 2 of getting a pointer

// Is this the same, other than being uninitialized?
struct Object* obj3_p = malloc(sizeof(struct Object)); // method 2 of getting a pointer

有没有只能使用一种方法的时候?

另外,作为旁注,为什么有些人会使用 malloc,这样做更好吗?

// malloc is casted to object:
struct Object* obj3_p = (Object*)malloc(sizeof(struct Object));

标签: cpointersmalloc

解决方案


我写了这段代码,希望它能帮助你更好地理解指针的一些特性:

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

struct Object { int id; };

struct Object *getObjectBold() {
    struct Object* obj2_p = &(struct Object) { .id = 2 };

    return obj2_p; // UB: Returns the address of a local object (the compound literal).
}

struct Object *getObject() {
    struct Object* obj3_p = malloc(sizeof(*obj3_p)); // Better way of calling malloc than using sizeof(struct Object).
    obj3_p->id = 3; // You don't need to do this.

    return obj3_p; // This needs to be freed later on!
}

int main(void) {
    struct Object obj1 = { .id = 1 };
    struct Object* obj1_p = &obj1;
    
    printf("obj1.id = %d\n", obj1_p->id); 
    obj1_p->id = 10; // You can change values using the pointer
    printf("obj1.id = %d\n", obj1_p->id); 

    // The only different thing with this case is that you don't
    // "lose" your object when setting the pointer to NULL 
    // (although you can only access it through the object, not through the pointer).

    obj1_p = NULL;
    printf("obj1.id = %d\n", obj1_p->id); // This won't work (undefined behaviour).
    printf("obj1.id = %d\n", obj1.id); // This will.


    struct Object* obj2_p = &(struct Object) { .id = 1 };
    obj2_p->id = 2; // You can change the id
    printf("obj2.id = %d\n", obj2_p->id);

    // If you make this pointer point to another address, you "lose" your object.
    obj2_p = NULL;
    printf("obj2.id = %d", obj2_p->id); // This won't work at all (undefined behaviour).


    // Both of these pointers point to objects in the stack, so, for example,
    // they don't work when returning from a function.
    obj2_p = getObjectBold();
    obj2_p->id = 20; // This won't work (undefined behaviour).
    printf("obj2.id = %d\n", obj2_p->id); // This works if you don't dereference the pointer.


    // The third case is not the same as the other two, since you are allocating memory on the heap.
    // THIS is a time where you can only use one of these three methods.
    struct Object *obj3_p = getObject(); // This works!
    printf("obj3.id = %d\n", obj3_p->id);
    obj3_p->id = 30; // This works now.
    printf("obj3.id = %d\n", obj3_p->id);

    free(obj3_p); // You need to do this if you don't want memory leaks.

    return 0;
}

这是注释掉未定义行为时的输出:

obj1.id = 1
obj1.id = 10
obj1.id = 10
obj2.id = 2
obj2.id = 2
obj3.id = 3
obj3.id = 30

我建议您查看这些链接,事实证明它们对我很有帮助:


推荐阅读