是否有一种简洁的语法来为结构指针分配和填充值(函数结束时不会被破坏)?
Is there a clean and short syntax to allocate and fill values for a struct pointer (that is not destroyed when function ends)?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ALLOC3(t, n, a, b, c) t* n = malloc(sizeof(t));\
memcpy(n, &((t){a, b, c}), sizeof(t));
int wickCount = 3;
char* color = "green";
char* scent = "Fresh Balsam";
typedef struct Candle_ {
int wickCount;
char* color;
char* scent;
} Candle;
Candle* maker1 () {
/* Imagine some code here that generates data,
but for now, I will use hard-coded values */
/* Create candle */
Candle* candle = malloc(sizeof(Candle));
candle->wickCount = wickCount;
candle->color = color;
candle->scent = scent;
return candle;
}
Candle* maker2 () {
Candle* candle = malloc(sizeof(Candle));
memcpy(candle, &((Candle){wickCount, color, scent}), sizeof(Candle));
return candle;
}
Candle* maker3 () {
Candle* candle = malloc(sizeof(Candle));
*candle = (Candle){wickCount, color, scent};
return candle;
}
Candle* maker4 () {
ALLOC3(Candle, candle, wickCount, color, scent);
return candle;
}
int main () {
Candle* candle = maker4();
/* Do some random things to check for memory leaks.
Let me know if there is a better way to do this. */
int temp = 5;
char* tempstr = "Some filler text...";
printf("Filler text...\n");
printf("%s\n", tempstr);
printf("Filler text...\n");
printf("==============\n");
printf("Values:\n");
/* Finally, print the values */
printf("%d\n", candle->wickCount);
printf("%s\n", candle->color);
printf("%s\n", candle->scent);
return 0;
}
Maker1 有效,但您必须按名称一一设置每个成员。
Maker2 有效,但仍需要 2 行和额外的语法。
Maker3这里好像能用,字少,但好像有时会造成内存泄露
Maker4 也可以,但我必须为所有数量的成员创建宏,例如 ALLOC1、ALLOC2、ALLOC3、ALLOC4 等等。肯定有比宏更少的组合方式。
全局范围有一个很好的语法:
Candle candle = {wickCount, color, scent};
有没有什么方法可以在函数内部以简短的语法分配和设置所有成员,而不会在函数结束时破坏值?
更新 我想出了一个适用于任意数量成员的宏:
#define ALLOC(s, v, p) s* p = malloc(sizeof(s));\
memcpy(p, &v, sizeof(s));
/* Then you can call it with this: */
ALLOC(Candle, ((Candle){wickCount, color, scent}), candle);
但它仍然不是最干净的,如果有更好的内置标准方法,我仍然不想使用宏。
您可以将整个代码放在一个宏中,然后将其称为“short”。您可能想了解 __VA_ARGS__
和可变参数宏。您的代码不处理分配错误。
#define ALLOCRET(TYPE, ...) \
TYPE *_tmp = malloc(sizeof(TYPE)); \
if (_tmp) \
*_tmp = (TYPE){ __VA_ARGS__ }; \
return _tmp;
Candle *maker5(void) {
ALLOCRET(Candle, wickCount, color, scent);
}
主观:总的来说,maker3
是最易读的,因此是首选。隐藏宏背后的东西可能会使您的代码难以维护且不可读。混合大写和小写的相似名称令人困惑 - Candle
和 candle
。考虑使用视觉上明显不同的名称来减少错误。使用结构时考虑写 struct
关键字。
我个人会去 mark3
但如果你真的喜欢 one-liners 你可以试试下面的宏:
#define DYNINIT(T, ...) ((T*)memcpy(malloc(sizeof(T)), &(T){ __VA_ARGS__ }, sizeof (T)))
...
Candle *maker5(void) {
return DYNINIT(Candle, wickCount, color, scent);
}
或者直接在main()中使用,例如
Candle* candle = DYNINIT(Candle, .wick = 2, .color="brown");
宏执行以下步骤:
- 为类型
T
和 malloc(sizeof(T))
分配内存
- 使用可变参数宏中的初始值设定项创建复合文字
(T){ __VA_ARGS__)
将宏参数作为初始化程序传递,解决了为每种类型制作专用 ALLOC
类宏的问题。
- 将复合文字复制到目标内存
memcpy(malloc(...), &(T){ ... }, sizeof (T))
注意memcpy()
returns目的地址
- 将从
memcpy
返回的 void*
转换为指向 T
的指针以确保某种类型安全。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ALLOC3(t, n, a, b, c) t* n = malloc(sizeof(t));\
memcpy(n, &((t){a, b, c}), sizeof(t));
int wickCount = 3;
char* color = "green";
char* scent = "Fresh Balsam";
typedef struct Candle_ {
int wickCount;
char* color;
char* scent;
} Candle;
Candle* maker1 () {
/* Imagine some code here that generates data,
but for now, I will use hard-coded values */
/* Create candle */
Candle* candle = malloc(sizeof(Candle));
candle->wickCount = wickCount;
candle->color = color;
candle->scent = scent;
return candle;
}
Candle* maker2 () {
Candle* candle = malloc(sizeof(Candle));
memcpy(candle, &((Candle){wickCount, color, scent}), sizeof(Candle));
return candle;
}
Candle* maker3 () {
Candle* candle = malloc(sizeof(Candle));
*candle = (Candle){wickCount, color, scent};
return candle;
}
Candle* maker4 () {
ALLOC3(Candle, candle, wickCount, color, scent);
return candle;
}
int main () {
Candle* candle = maker4();
/* Do some random things to check for memory leaks.
Let me know if there is a better way to do this. */
int temp = 5;
char* tempstr = "Some filler text...";
printf("Filler text...\n");
printf("%s\n", tempstr);
printf("Filler text...\n");
printf("==============\n");
printf("Values:\n");
/* Finally, print the values */
printf("%d\n", candle->wickCount);
printf("%s\n", candle->color);
printf("%s\n", candle->scent);
return 0;
}
Maker1 有效,但您必须按名称一一设置每个成员。
Maker2 有效,但仍需要 2 行和额外的语法。
Maker3这里好像能用,字少,但好像有时会造成内存泄露
Maker4 也可以,但我必须为所有数量的成员创建宏,例如 ALLOC1、ALLOC2、ALLOC3、ALLOC4 等等。肯定有比宏更少的组合方式。
全局范围有一个很好的语法:
Candle candle = {wickCount, color, scent};
有没有什么方法可以在函数内部以简短的语法分配和设置所有成员,而不会在函数结束时破坏值?
更新 我想出了一个适用于任意数量成员的宏:
#define ALLOC(s, v, p) s* p = malloc(sizeof(s));\
memcpy(p, &v, sizeof(s));
/* Then you can call it with this: */
ALLOC(Candle, ((Candle){wickCount, color, scent}), candle);
但它仍然不是最干净的,如果有更好的内置标准方法,我仍然不想使用宏。
您可以将整个代码放在一个宏中,然后将其称为“short”。您可能想了解 __VA_ARGS__
和可变参数宏。您的代码不处理分配错误。
#define ALLOCRET(TYPE, ...) \
TYPE *_tmp = malloc(sizeof(TYPE)); \
if (_tmp) \
*_tmp = (TYPE){ __VA_ARGS__ }; \
return _tmp;
Candle *maker5(void) {
ALLOCRET(Candle, wickCount, color, scent);
}
主观:总的来说,maker3
是最易读的,因此是首选。隐藏宏背后的东西可能会使您的代码难以维护且不可读。混合大写和小写的相似名称令人困惑 - Candle
和 candle
。考虑使用视觉上明显不同的名称来减少错误。使用结构时考虑写 struct
关键字。
我个人会去 mark3
但如果你真的喜欢 one-liners 你可以试试下面的宏:
#define DYNINIT(T, ...) ((T*)memcpy(malloc(sizeof(T)), &(T){ __VA_ARGS__ }, sizeof (T)))
...
Candle *maker5(void) {
return DYNINIT(Candle, wickCount, color, scent);
}
或者直接在main()中使用,例如
Candle* candle = DYNINIT(Candle, .wick = 2, .color="brown");
宏执行以下步骤:
- 为类型
T
和malloc(sizeof(T))
分配内存
- 使用可变参数宏中的初始值设定项创建复合文字
(T){ __VA_ARGS__)
将宏参数作为初始化程序传递,解决了为每种类型制作专用 ALLOC
类宏的问题。
- 将复合文字复制到目标内存
memcpy(malloc(...), &(T){ ... }, sizeof (T))
注意memcpy()
returns目的地址
- 将从
memcpy
返回的void*
转换为指向T
的指针以确保某种类型安全。