作为家庭作业,我必须编写一个仅使用malloc
和free
函数来更改数组大小的函数。
我知道如何使用realloc
,但是我不知道如何使用malloc
。
typedef struct{
int *tab;
int size;
}arr;
我需要编写此函数:
void changeSizeDyn(arr *Dyn_arr, int size){
//
}
如作业中所述:它只需要一个重新分配和一个内存释放,以及旧数组中元素的一个副本。
我进行了很多搜索,但仅使用realloc
找到了结果。
是否可以不使用realloc
来做到这一点?
答案 0 :(得分:5)
答案 1 :(得分:1)
此功能乍一看并不简单。
您在这里。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef struct
{
int *tab;
int size;
} arr;
int changeSizeDyn( arr *Dyn_arr, int size )
{
int success = 1;
if ( Dyn_arr->size != size )
{
int *tmp = NULL;
if ( size != 0 )
{
tmp = malloc( size * sizeof( int ) );
success = tmp != NULL;
if ( success )
{
int n = 0;
if ( Dyn_arr->size != 0 )
{
n = size < Dyn_arr->size ? size : Dyn_arr->size;
memcpy( tmp, Dyn_arr->tab, n * sizeof( int ) );
}
if ( n < size ) memset( tmp + n, 0, ( size - n ) * sizeof( int ) );
}
}
if ( success )
{
free( Dyn_arr->tab );
Dyn_arr->tab = tmp;
Dyn_arr->size = size;
}
}
return success;
}
int main( void )
{
arr a = { NULL, 0 };
int size = 10;
if ( changeSizeDyn( &a, size ) )
{
for ( int i = 0; i < size; i++ ) a.tab[i] = i;
for ( int i = 0; i < size; i++ ) printf( "%d ", a.tab[i] );
putchar( '\n' );
}
size = 5;
if ( changeSizeDyn( &a, size ) )
{
for ( int i = 0; i < size; i++ ) a.tab[i] = i;
for ( int i = 0; i < size; i++ ) printf( "%d ", a.tab[i] );
putchar( '\n' );
}
size = 0;
if ( changeSizeDyn( &a, size ) )
{
for ( int i = 0; i < size; i++ ) a.tab[i] = i;
for ( int i = 0; i < size; i++ ) printf( "%d ", a.tab[i] );
putchar( '\n' );
}
assert( a.tab == NULL && a.size == 0 );
}
程序输出为
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4
该函数具有返回类型int
,以指示其调用是否成功。您需要一种方法来确定函数调用是否成功。否则将无法确定。因此,使用类型void
作为函数的返回类型是一个坏主意。
默认情况下,该函数将与旧数组的元素不对应的所有新元素设置为零。实际上,这不是必需的,但是可以使结构的使用更加清晰。
如果用户传递的大小等于0,则该函数将释放旧数组并将数据成员tab
设置为NULL
。
如果数组的新大小和旧大小相等,则该函数不执行任何操作。
请注意,最好将结构的数据成员size
声明为类型size_t
。否则,您需要在函数size
中是否添加负号。我之所以没有这样做,是因为我想您确实会在结构(和函数)声明中使用类型size_t
而不是类型int
。
答案 2 :(得分:1)
struct Arr {
int *tab;
ptrdiff_t nmemb;
};
假设您最初是这样分配数组的:
struct Arr x;
x.nmemb = 7;
x.tab = malloc(sizeof(*x.tab) * x.nmemb);
您应该使用以下函数重新分配它:
void change_size_dyn(struct Arr *dyn_arr, ptrdiff_t nmemb)
{
struct Arr old;
ptrdiff_t cp_nmemb;
if (!dyn_arr)
return;
old = *dyn_arr;
if (nmemb <= 0)
goto err;
dyn_arr->tab = malloc(sizeof(*dyn_arr->tab) * nmemb);
dyn_arr->nmemb = nmemb;
cp_sz = MIN(old.nmemb, nmemb);
memcpy(dyn_arr->tab, old.tab, cp_nmemb);
free(old.tab);
return;
err:
dyn_arr->tab = NULL;
dyn_arr->nmemb = 0;
free(old.tab);
}
应该这样称呼:
change_size_dyn(&x, 9);
即使是第一次分配,您也可以使用此功能(尽管您应该首先将NULL
和0
都设置为两个值)。您也不需要添加免费;输入0即可为您完成,就像realloc
一样:
int main(void)
{
struct Arr x = {0};
change_size_dyn(&x, 5);
/* ... */
change_size_dyn(&x, 9);
/* ... */
cleanup:
change_size_dyn(&x, 0);
return 0;
}
如果您传递的结构中dyn_arr->nmemb
已经是负值(不应发生),则行为是不确定的(该负值将进入memcpy
,将其包装为一个非常大的值)。高size_t
,这会使数组溢出)。我不想进行检查,因为在任何非越野车场景中都没有必要。
答案 3 :(得分:1)
是否甚至可以在不使用
realloc
的情况下做到这一点?
可以。
例如,您可以这样做:
#include <stdlib.h> /* for malloc () and free () and EXIT_xxx macros. */
#include <stdio.h> /* for perror */
typedef struct{
int *tab;
size_t size; /* Prefer using size_t for (memory) sizes over using a
signed int. */
} arr;
void changeSizeDyn(arr *parr, size_t size)
{
if (!parr && !parr->tab)
{
errno = EINVAL;
}
else
{
arr tmp = {
malloc(size * sizeof *tmp.tab),
size
};
if (tmp.size && !tmp.tab)
{
perror("malloc() failed");
}
else
{
for (
size_t m = (tmp.size < parr->size) ?tmp.size :parr->size, i = 0;
i < m;
++i)
{
tmp.tab[i] = parr->tab[i];
}
free(parr->tab);
*parr = tmp;
errno = 0;
}
}
}
/* A main() to test the above: */
int main(void)
{
const size_t s = 42;
arr a = {
malloc(s * sizeof *a.tab),
s
};
if (a.size && !a.tab)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}
/* populate a.tab[0] to a.tab[a.size - 1] here. */
changeSizeDyn(&a, 43);
if (0 != errno)
{
perror("changeSizeDyn() failed");
exit(EXIT_FAILURE);
}
/* Use a.tab[0] to a.tab[a.size - 1] here. */
free(a.tab);
a.size = 0;
}
答案 4 :(得分:-2)
with tf.Session(graph=self.graph) as sess:
sess.run(self.train_step,
feed_dict={
self.lstm_output_ph: self.last_output,
self.reward_ph: reward,
self.previous_q_ph: previous_q
})
和您的类型(略有变化)
void *onlymallocrealloc(void *ptr, size_t oldsize, size_t newsize)
{
void *newmem = malloc(newsize);
if(ptr && newmem)
{
memcpy(newmem, ptr, oldsize);
free(ptr);
}
return newmem;
}
typedef struct{
int size;
int tab[];
}arr;
arr *onlymalloc(arr *ptr, size_t newsize)
{
ptr = onlymallocrealloc(ptr, ptr -> size * sizoef(ptr -> tab[0]) + sizeof(*ptr), newsize * sizoef(ptr -> tab[0]) + sizeof(*ptr));
if(ptr)
{
ptr -> size = newsize;
}
return ptr;
}