在C中声明指针的方法 我只学习C不到一个星期(我的C++和其他语言的知识有帮助),我对指针和声明方式感到困惑。
下面,我使用一个名为Object的简单结构:在C中声明指针的方法 我只学习C不到一个星期(我的C++和其他语言的知识有帮助),我对指针和声明方式感到困惑。,c,pointers,malloc,C,Pointers,Malloc,下面,我使用一个名为Object的简单结构: struct对象{int id;}; 以下用于创建指针的方法是否以不同的方式执行相同的操作 struct Object obj1={.id=1}; 结构对象*obj1\u p=&obj1;//获取指针的方法1 //同样,只是复合文字? 结构对象*obj2_p=&(结构对象){.id=1};//获取指针的方法2 //除了未初始化之外,这是相同的吗? struct Object*obj3_p=malloc(sizeof(struct Object));
struct对象{int id;};
以下用于创建指针的方法是否以不同的方式执行相同的操作
struct Object obj1={.id=1};
结构对象*obj1\u p=&obj1;//获取指针的方法1
//同样,只是复合文字?
结构对象*obj2_p=&(结构对象){.id=1};//获取指针的方法2
//除了未初始化之外,这是相同的吗?
struct Object*obj3_p=malloc(sizeof(struct Object));//获取指针的方法2
是否有一段时间你只能使用一种方法
另外,作为旁注,为什么有些人投malloc,这样做更好吗
//malloc被强制转换为对象:
struct Object*obj3_p=(Object*)malloc(sizeof(struct Object));
这两种“方法”的作用完全相同。正如你所说,第二个只是一个例子
这将为
struct对象
分配足够的内存,而无需对其进行初始化。而不是您,因为malloc
返回void*
,它会自动安全地升级到任何其他指针。但是如果您这样做,您应该将其强制转换为struct Object*
,而不是Object*
struct Object *obj3_p = (struct Object*) malloc(sizeof(struct Object));
不过看起来很笨重。。。我更喜欢这样做:
struct Object *obj3_p = malloc(sizeof *obj3_p);
这两种“方法”的作用完全相同。正如你所说,第二个只是一个例子
这将为
struct对象
分配足够的内存,而无需对其进行初始化。而不是您,因为malloc
返回void*
,它会自动安全地升级到任何其他指针。但是如果您这样做,您应该将其强制转换为struct Object*
,而不是Object*
struct Object *obj3_p = (struct Object*) malloc(sizeof(struct Object));
不过看起来很笨重。。。我更喜欢这样做:
struct Object *obj3_p = malloc(sizeof *obj3_p);
我写了这段代码,希望它能帮助您更好地理解指针的一些特性:
#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;
}
我建议您查看这些链接,它们对我很有帮助:
- 我写了这段代码,希望它能帮助您更好地理解指针的一些特性:
#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;
}
我建议您查看这些链接,它们对我很有帮助:
- 你的问题中有两个截然不同的主题
struct Object* obj1_p = .......;
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
pointer object initialization
definition
type *objectname;
struct Object *valid1(void) //valid
{
struct Object* obj3_p = malloc(sizeof(*obj3_p));
return obj3_p;
}
struct Object obj1 = { .id = 1 };
struct Object *valid2(void) // valid
{
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid1(void) // invalid
{
struct Object obj1 = { .id = 1 };
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid2(void) // invalid
{
struct Object* obj3_p = &(struct Object){ .id = 1 };
return obj3_p;
}
另外,作为旁注,为什么有些人投马洛克,它更好吗
去做吗
如果没有malloc
的原型,它会使警告静音,因此被视为不良做法。最好不要投。现代编译器和最新的C标准不允许在没有原型的情况下使用函数
最好使用
sizeof(object)
而不是sizeof(type)
来更改对象的类型,就像您需要更改程序中出现的sizeof(type)
的oll一样。很容易漏掉一些错误,也很难发现错误。在你的问题中有两个截然不同的主题
struct Object* obj1_p = .......;
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^
pointer object initialization
definition
type *objectname;
struct Object *valid1(void) //valid
{
struct Object* obj3_p = malloc(sizeof(*obj3_p));
return obj3_p;
}
struct Object obj1 = { .id = 1 };
struct Object *valid2(void) // valid
{
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid1(void) // invalid
{
struct Object obj1 = { .id = 1 };
struct Object* obj3_p = &obj1;
return obj3_p;
}
struct Object *invalid2(void) // invalid
{
struct Object* obj3_p = &(struct Object){ .id = 1 };
return obj3_p;
}
另外,作为旁注,为什么有些人投马洛克,它更好吗
去做吗
如果没有malloc
的原型,它会使警告静音,因此被视为不良做法。最好不要投。现代编译器和最新的C标准不允许在没有原型的情况下使用函数
最好使用
sizeof(object)
而不是sizeof(type)
来更改对象的类型,就像您需要更改程序中出现的sizeof(type)
的oll一样。很容易遗漏一些错误,也很难发现错误。首先,让我们理清一些术语-
您以完全相同的方式声明所有三个指针:
struct Object* objn_p ...
声明说明符是struct Object
,声明符是*obj1\u p
,初始值设定项是=&obj\u 1
我知道声明指针对象的C++约定是“代码> t*p< /COD>,但是语法实际上是代码> T(*p)< /COD> -<代码> */COD>运算符总是绑定到声明符而不是类型说明符。如果你写
T*p,q
则只有p
被声明为指向T
的指针q
被声明为T
的一个实例。我知道为什么C++约定存在,我知道它的合理性,但是它确实错误地说明了声明语法在C和C++中都是如何工作的,我认为使用它是错误的。大多数C程序员将使用
struct Object *obj2_p = &(struct Object){ .id = 1 };
printf( "%d %d %d", obj1.id, obj1_p->id, (*obj1_p).id );
printf( "%d %d", obj2_p->id, (*obj2_p).id );
struct Object *obj3_p = malloc( sizeof( struct Object ) );
int *p = (int *) malloc( sizeof *p * N );
int *p = NULL;
...
p = (int *) malloc( sizeof *p * N );
int *p = malloc( sizeof *p * N );
int *p = NULL;
...
p = malloc( sizeof *p * N );