提问人:Briac Bruneau Sunkkie 提问时间:11/12/2023 最后编辑:Briac Bruneau Sunkkie 更新时间:11/12/2023 访问量:71
是否可以将结构成员名称作为函数中的参数传递?
Is it possible to pass a struct member name as an argument in a function?
问:
我正在编写启发式方法来解决网格问题,但我最终在函数体中重复了 4 次相同的代码块,每次差异都非常小,因此建议我编写一个内联函数以使其看起来更好。
我的网格是一个具有成员大小的结构体,线条由另一个结构体表示:
typedef struct
{
int size;
binline *lines;
} grid_t;
和
typedef struct
{
uint64_t ones;
uint64_t zeros;
} gridline;
1(resp zeros)是一个二进制整数,其中位表示 1(resp zeros)在网格中的位置,我选择以这种方式表示线,因为它们可以是 1 或 0 或空。
所以我现在有一个函数,条目看起来像,在正文中我测试“c”是 ONE 还是 ZERO,然后应用相应的启发式方法。static inline bool subheuristic(grid_t *grid, ..., ..., char c)
问题是它并没有真正减少代码大小......
我想知道是否可以将“一些”作为参数,然后在正文中立即使用它来访问,例如,在这种情况下,这将真正减小代码大小。grid->gridline.some
答:
0赞
tstanisl
11/12/2023
#1
有一些方法可以在 C 中实现所需的功能。
不能将成员的名称传递给函数,但可以在结构中传递成员的偏移量。偏移量可以从 中定义的标准宏获得。offsetof
stddef.h
#include <stddef.h>
uint64_t get_grid_bits(const gridline *gl, size_t offset) {
return *(uint64_t*)( (char*)gl + offset );
}
...
gridline gl = { .ones = 13, .zeros = 42 };
get_grid_bits(&gl, offsetof(gridline, ones)); // return 13
get_grid_bits(&gl, offsetof(gridline, zeros)); // return 42
请注意,该行为完全由 C 标准定义,因为任何对象的任何部分都可以通过类型的指针算术来访问。char*
像魅力一样工作。
评论
0赞
Briac Bruneau Sunkkie
11/12/2023
删除 const 关键字,是否可以修改函数中 1/0s 字段的值?假设 I 偏移量和网格指针作为参数
0赞
tstanisl
11/12/2023
@BriacBruneauSunkkie,是的,假设原始对象是在没有限定符的情况下声明的。 很好,但是会调用未定义的行为。const
gridline gl = { ... }
const gridline gl = { ... }
0赞
0___________
11/12/2023
仅当使用 offsetof 时,才像超级按钮一样工作。但这并不妨碍通过任何其他论点。然后它将调用 UB。要使其 100% 无 UB,您需要添加 asserst 或运行时检查
0赞
tstanisl
11/12/2023
@0___________.可以使用宏#define get_grid_bits(gl,member) get_grid_bits(gl, offsetof(gridline, member))
0赞
0___________
11/12/2023
?godbolt.org/z/njKq4Kb8r
0赞
0___________
11/12/2023
#2
这在 C 语言中是不可能的,但我会使用一个内联函数,当您将常量表达式作为 和 传递时,该函数将很好地优化为非常简单的操作bit
type
typedef struct
{
uint64_t data[2];
} gridline;
typedef enum {zeroes, ones} type;
static inline __attribute__((always_inline)) uint64_t get_grid_bits(const gridline * restrict gl, const type t)
{
return gl -> data[t];
}
static inline __attribute__((always_inline)) void set_grid_bit(gridline * restrict gl, const type t, int bit)
{
gl -> data[t] |= 1ULL << bit;
}
static inline __attribute__((always_inline)) void reset_grid_bit(gridline * restrict gl, const type t, int bit)
{
gl -> data[t] &= ~(1ULL << bit);
}
static inline __attribute__((always_inline)) int get_grid_bit(const gridline * restrict gl, const type t, int bit)
{
return !!(gl -> data[t] & (1ULL << bit));
}
评论