假设我想定义一个表示向量长度及其值的结构:
struct Vector{
double* x;
int n;
};
现在,假设我想定义一个向量y,并为它分配内存。
struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
我在互联网上的搜索显示,我应该单独为x分配内存。
y->x = (double*)malloc(10*sizeof(double));
但是,似乎我为y-〉x分配了两次内存,一次是为y分配内存,另一次是为y-〉x分配内存,这似乎是浪费内存。如果让我知道编译器真正做的是什么,以及初始化y和y-〉x的正确方法,我将非常感激。
8条答案
按热度按时间r1zhe5dt1#
不,您 * 没有 * 为
y->x
分配内存两次。相反,您是在为结构(其中包括一个指针)分配内存,* 加上 * 该指针要指向的内容。
你可以这样想:
您实际上需要 * 两个 * 分配(
1
和2
)来存储所需的一切。此外,您的类型应该是
struct Vector *y
,因为它是一个指针,并且您永远不应该在C中强制转换malloc
的返回值。它可以隐藏某些您不想隐藏的问题,并且C完全能够隐式地将
void*
返回值转换为任何其他指针。当然,您可能希望封装这些向量的创建过程,以便更容易地管理它们,例如在头文件
vector.h
中包含以下内容:然后,在
vector.c
中,您可以使用实际的函数来管理向量:通过像这样封装向量管理,您可以确保向量要么完全构建,要么根本不构建--它们不可能构建一半。
它还允许您在将来完全更改底层数据结构而不影响客户端。例如:
如果需要,您还可以添加更多功能,例如安全地设置或获取向量值(请参见标题中的注解代码)。
例如,您可以(作为一个选项)静默地忽略有效范围之外的设置值,并在获取这些值时返回零。或者,您可以引发某种描述的错误,或尝试自动展开覆盖下的向量(1)。
在使用向量方面,一个简单的示例类似于以下(非常基本的)
main.c
(1)这种可扩展向量的潜力需要进一步解释。
许多向量实现将容量和大小分开,前者是在需要重新分配之前可以使用多少元素,后者是实际的向量大小(总是〈=容量)。
当扩展时,你希望以这样一种方式进行扩展,你不需要做很多,因为这可能是一个昂贵的操作。例如,你可以添加比严格需要的多5%,这样,在一个循环中连续添加一个元素,它不必为每一个单独的项目重新分配。
mrwjdhj32#
第一次,您为
Vector
分配内存,这意味着变量x
、n
。但是
x
还没有指向任何有用的东西。这就是为什么还需要第二次分配的原因。
ozxc1zmp3#
原则上你已经做对了,你需要两个
malloc()
。只是一些评论:
应该是
在第一行中,为Vector对象分配内存。
malloc()
返回一个指向已分配内存的指针,因此y必须是一个Vector指针。在第二行中,为一个包含10个double的数组分配内存。在C语言中,你不需要显式的强制转换,写
sizeof *y
而不是sizeof(struct Vector)
对于类型安全更好,此外,它节省了输入。你可以重新排列你的结构体,然后像这样执行一个
malloc()
:vtwuwzda4#
几个点
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector));
是错误的它应该是
struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
,因为y
持有指向struct Vector
的指针。第一个
malloc()
只分配了足够容纳Vector结构(指向double + int的指针)的内存第二个
malloc()
实际分配内存以容纳10双精度浮点数。kkbh8khc5#
当你为
struct Vector
分配内存时,你只为指针x
分配内存,也就是说,为空间分配内存,它的值,包含地址,将被放置在那里。所以,这样你就不会为y.x
将引用的块分配内存。xlpyo6sf6#
第一个malloc为struct分配内存,包括x(指向double的指针)的内存。第二个malloc为x指向的double值分配内存。
kuarbcqp7#
实际上,你可以在一个malloc中同时分配Vector和数组来完成这一操作。
这会分配Vector 'y',然后使y-〉x指向紧接在Vector结构体之后的额外分配的数据(但在同一内存块中)。
如果需要调整向量的大小,你应该按照推荐的两个分配来做,这样内部的y-〉x数组就可以在保持向量结构体'y'不变的情况下调整大小。
krugob8w8#
当你
malloc(sizeof(struct_name))
时,它会自动为结构体的全部大小分配内存,你不需要malloc里面的每个元素。使用
-fsanitize=address
标志检查程序内存的使用情况。