union vs void*,哪个更好?
union vs void*, which is better for what?
刚开始学union的时候还不是很明显,但是学了C++之后运行时候polymorphism就有了思路。为什么我使用 union
而不是 void*
?我为两者创建了一个简短的代码示例。
这里是 union
例子:
#include <stdio.h>
#include <stdlib.h>
const int N = 10;
union int_double_t
{
int i;
double d;
};
enum int_double_label
{
INT, DOUBLE
};
struct labeled_int_double_t
{
enum int_double_label label;
union int_double_t value;
};
int main()
{
struct labeled_int_double_t u[N];
for (int i = 0; i < N; ++i)
{
if (rand() % 2)
{
u[i].label = INT;
u[i].value.i = i;
printf("array[%i]: %s\t%i\n", i, u[i].label ? "double" : "int", u[i].value.i);
}
else
{
u[i].label = DOUBLE;
u[i].value.d = i + .1;
printf("array[%i]: %s\t%f\n", i, u[i].label ? "double" : "int", u[i].value.d);
}
}
}
这里是 void*
例子:
#include <stdio.h>
#include <stdlib.h>
const int N = 10;
enum int_double_label
{
INT, DOUBLE
};
struct labeled_int_double_t
{
enum int_double_label label;
void* value;
};
int main()
{
struct labeled_int_double_t u[N];
for (int i = 0; i < N; ++i)
{
if (rand() % 2)
{
u[i].label = INT;
u[i].value = malloc(sizeof(int));
*(int*)u[i].value = i;
printf("array[%i]: %s\t%i\n", i, u[i].label ? "double" : "int", *(int*)u[i].value);
free(u[i].value);
}
else
{
u[i].label = DOUBLE;
u[i].value = malloc(sizeof(double));
*(double*)u[i].value = i + .1;
printf("array[%i]: %s\t%f\n", i, u[i].label ? "double" : "int", *(double*)u[i].value);
free(u[i].value);
}
}
}
两者均按预期编译:gcc -W -Wall -Wextra -pedantic -std=c99
,均 运行。
这是输出:
array[0]: int 0
array[1]: int 1
array[2]: double 2.100000
array[3]: double 3.100000
array[4]: int 4
array[5]: double 5.100000
array[6]: double 6.100000
array[7]: double 7.100000
array[8]: double 8.100000
array[9]: double 9.100000
我有点看出区别了。使用 union
,我只能使用堆栈内存,但还有其他根本区别吗?
虽然您知道自己在做什么,并且仍然知道自己做了什么,但并没有太大区别。
但除此之外(代码是同事写的,或者是你在海滩上度过三周假期之前写的)你会为任何强制清晰和编译器可以为你检测错误的任何小事感到高兴。
对于不断处理相关代码的单身程序员来说,这似乎无关紧要,但对于旧的、大型的或多地点的项目,我觉得“*void
是不吉利的。”如此之多以至于在写这篇文章之前我需要一些时间来意识到这不是一般规则。 ;-)
哪个更好取决于更高级别的上下文使用。有些东西没有显示。
在 select 个案例中,每种方法都更优。
union
亲:简单。
Pro: 没有分配错误。
Pro: 只需要简单的复制。
Pro: union
.
的尺寸信息部分
---: 所有对象大小相同。
缺点:当可能的对象类型在大小上 大 不同时会造成浪费。
malloc
专业版:每个对象大小合适。
缺点:每个对象都有指针开销。
缺点:分配可能会失败。
缺点:只复制指针。需要更多代码来复制引用的对象。
缺点:小对象分配会破坏内存。
缺点:需要伴侣 free()
。
--
对于 int i, double d
,我更有可能使用 union
方法。
旁白:进步的反义词是什么?
国会
刚开始学union的时候还不是很明显,但是学了C++之后运行时候polymorphism就有了思路。为什么我使用 union
而不是 void*
?我为两者创建了一个简短的代码示例。
这里是 union
例子:
#include <stdio.h>
#include <stdlib.h>
const int N = 10;
union int_double_t
{
int i;
double d;
};
enum int_double_label
{
INT, DOUBLE
};
struct labeled_int_double_t
{
enum int_double_label label;
union int_double_t value;
};
int main()
{
struct labeled_int_double_t u[N];
for (int i = 0; i < N; ++i)
{
if (rand() % 2)
{
u[i].label = INT;
u[i].value.i = i;
printf("array[%i]: %s\t%i\n", i, u[i].label ? "double" : "int", u[i].value.i);
}
else
{
u[i].label = DOUBLE;
u[i].value.d = i + .1;
printf("array[%i]: %s\t%f\n", i, u[i].label ? "double" : "int", u[i].value.d);
}
}
}
这里是 void*
例子:
#include <stdio.h>
#include <stdlib.h>
const int N = 10;
enum int_double_label
{
INT, DOUBLE
};
struct labeled_int_double_t
{
enum int_double_label label;
void* value;
};
int main()
{
struct labeled_int_double_t u[N];
for (int i = 0; i < N; ++i)
{
if (rand() % 2)
{
u[i].label = INT;
u[i].value = malloc(sizeof(int));
*(int*)u[i].value = i;
printf("array[%i]: %s\t%i\n", i, u[i].label ? "double" : "int", *(int*)u[i].value);
free(u[i].value);
}
else
{
u[i].label = DOUBLE;
u[i].value = malloc(sizeof(double));
*(double*)u[i].value = i + .1;
printf("array[%i]: %s\t%f\n", i, u[i].label ? "double" : "int", *(double*)u[i].value);
free(u[i].value);
}
}
}
两者均按预期编译:gcc -W -Wall -Wextra -pedantic -std=c99
,均 运行。
这是输出:
array[0]: int 0
array[1]: int 1
array[2]: double 2.100000
array[3]: double 3.100000
array[4]: int 4
array[5]: double 5.100000
array[6]: double 6.100000
array[7]: double 7.100000
array[8]: double 8.100000
array[9]: double 9.100000
我有点看出区别了。使用 union
,我只能使用堆栈内存,但还有其他根本区别吗?
虽然您知道自己在做什么,并且仍然知道自己做了什么,但并没有太大区别。
但除此之外(代码是同事写的,或者是你在海滩上度过三周假期之前写的)你会为任何强制清晰和编译器可以为你检测错误的任何小事感到高兴。
对于不断处理相关代码的单身程序员来说,这似乎无关紧要,但对于旧的、大型的或多地点的项目,我觉得“*void
是不吉利的。”如此之多以至于在写这篇文章之前我需要一些时间来意识到这不是一般规则。 ;-)
哪个更好取决于更高级别的上下文使用。有些东西没有显示。
在 select 个案例中,每种方法都更优。
union
亲:简单。
Pro: 没有分配错误。
Pro: 只需要简单的复制。
Pro: union
.
的尺寸信息部分
---: 所有对象大小相同。
缺点:当可能的对象类型在大小上 大 不同时会造成浪费。
malloc
专业版:每个对象大小合适。
缺点:每个对象都有指针开销。
缺点:分配可能会失败。
缺点:只复制指针。需要更多代码来复制引用的对象。
缺点:小对象分配会破坏内存。
缺点:需要伴侣 free()
。
--
对于 int i, double d
,我更有可能使用 union
方法。
旁白:进步的反义词是什么?
国会