【问题标题】:Generic value initialized allocator通用值初始化分配器
【发布时间】:2020-04-19 13:25:15
【问题描述】:

搞乱/学习 C。我想要一个用于将堆栈值移动到堆中的单线器,这是我能想到的最好的方法。

#define defheapify(nm, T, sz) \
  T* heapify_##nm (const T x) { \
    T *nx = malloc(sz); \
    nx[0] = x; \
    return nx; \
  }

defheapify(char, char, sizeof(char));
defheapify(uchar, unsigned char, sizeof(unsigned char));
defheapify(short_int, short int, sizeof(short int));
defheapify(ushort_int, unsigned short int, sizeof(unsigned short int));
defheapify(int, int, sizeof(int));
defheapify(uint, unsigned int, sizeof(unsigned int));
defheapify(long_int, long int, sizeof(long int));
defheapify(ulong_int, unsigned long int, sizeof(unsigned long int));
defheapify(long_long_int, long long int, sizeof(long long int));
defheapify(ulong_long_int, unsigned long long int, sizeof(unsigned long long int));
defheapify(float, float, sizeof(float));
defheapify(double, double, sizeof(double));
defheapify(long_double, long double, sizeof(long double));

它似乎有效:

  short int *si = heapify_short_int(20);
  printf("%d\n", ((int*)si)[0]); /* => 20 */

有没有更好的方法来做到这一点?

【问题讨论】:

  • 你为什么要这样做?
  • 除了可能有*nx = x 而不是使用[0] 并添加检查以确保malloc 不会返回NULL 我唯一的原因就是。
  • 分割堆的好方法。
  • @EugeneSh。无论您是通过为所有类型定义函数,还是在每个地方写出 malloc 代码,都会发生这种情况。
  • @Christian Gibbons,我的第一个想法是他们想要一个初始化分配器,但初始化只适用于简单类型。所以是的,为什么要动态地动态分配简单的值?

标签: c malloc dynamic-memory-allocation


【解决方案1】:

因为这是 C:

void * heapify (const void *p, size_t sz) {
    void *x = malloc(sz);
    if (x) memcpy(x, p, sz);
    return x;
}

那么,如果你坚持:

#define defheapify(nm, T, sz) \
T* heapify_##nm (const T x) { return heapify(&x, sz); }

但是,如果你有T,sz 是多余的,所以:

#define defheapify(nm, T) \
T* heapify_##nm (const T x) { return heapify(&x, sizeof(x)); }

但是,如果您只关心问题中列出的类型,则可以改用_Generic 开关并简化您的界面。使用下面的代码,您可以消除找出正在处理的变量或常量类型的任务。只需始终致电heapify_any。

#define heapify_T(T, X) \
(T *)heapify(&(struct{ T x; }){X}.x, sizeof(T))

#define heapify_G(T, X) T:heapify_T(T, X)

#define heapify_any(X) _Generic( \
X, \
heapify_G(_Bool, X), \
heapify_G(char, X), \
heapify_G(signed char, X), \
heapify_G(unsigned char, X), \
heapify_G(short int, X), \
heapify_G(unsigned short int, X), \
heapify_G(int, X), \
heapify_G(unsigned int, X), \
heapify_G(long int, X), \
heapify_G(unsigned long int, X), \
heapify_G(long long int, X), \
heapify_G(unsigned long long int, X), \
heapify_G(float, X), \
heapify_G(double, X), \
heapify_G(long double, X), \
default:(void)0 \
)

C 中没有文字 short(或 char 或 _Bool)值,因此您需要一个变量或强制转换才能使用上面的 heapify_any 宏。

short int *si = heapify_any((short)20);
printf("%hd\n", *si);

Try it online!

【讨论】:

  • 我相当肯定 C 预处理器限制了 sizeof。
  • @crinklywrappr 你是什么意思?
  • 这里不是这样。我们不要求预处理器评估sizeof,我们只是要求它按原样放置宏正在扩展的位置。
  • “_Bool 用户传奇联盟协会热线整合团队”(b.u.l.l.s.h.i.t.) 希望投诉_Bool 不在_Generic 列表中。他们的座右铭:“不要踩_Bool!?
  • 我不认为wchar_t(和其他)是内在类型。 “wchar_t,<stddef.h> 标头中定义的整数类型”。可能与其他人发生碰撞。
猜你喜欢
  • 2020-05-04
  • 2016-06-24
  • 2018-11-26
  • 1970-01-01
  • 2020-08-21
  • 2018-02-18
  • 2018-02-06
  • 2021-06-03
  • 1970-01-01
相关资源
最近更新 更多