我正在處理 C 中的一個問題,我想創建一個動態增長的陣列,如果可能的話,對不同的資料型別使用相同的函式。目前我有一個名為的結構Array,它使用一個名為 void 的資料型別*array,它是一個指向陣列的指標。它還保存len了哪些存盤了陣列的活動長度,size哪些保存了已分配記憶體elem的長度,哪些存盤了用于動態增長陣列的資料型別的長度。
另外,我正在使用三個功能。該函式完成了為結構中的變數分配記憶體并實體化除結構元素之一之外的所有元素initiate_array的繁重作業。array該函式init_array充當包裝器initiate_array并實體化elem結構中的變數。最后,該函式append_array將資料/索引添加到陣列并在必要時重新分配記憶體。
此時Arraystruct、functionsinitiate_array和init_array資料型別無關;但是,對于變數append_array是硬編碼的。int我試圖通過將輸入設為來使append_array某種資料型別獨立,但隨后在每個位置都出現編譯時錯誤,代碼告訴我不能強制轉換為 void。int itemvoid item((int *)array->array)[array->len - 1] = item
我的代碼在下面,有沒有人建議我如何實作append_array函式以獨立于資料型別item?
注意:我還有一個在執行結束時釋放記憶體的功能,但我在這個問題中省略了它,因為它不相關。
陣列.h
#ifndef ARRAY_H
#define ARRAY_H
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
void *array;
size_t len;
size_t size;
int elem;
} Array;
void initiate_array(Array *array, size_t num_indices);
Array init_array(int size, size_t num_indices);
void append_array(Array *array, int item);
#endif /* ARRAY_H */
陣列.c
#include "array.h"
void initiate_array(Array *array, size_t num_indices) {
void *pointer;
pointer = malloc(num_indices * array->elem);
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
free(pointer);
exit(0);
}
else {
array->array = pointer;
array->len = 0;
array->size = num_indices;
}
}
Array init_array(int size, size_t num_indices) {
Array array;
array.elem = size;
initiate_array(&array, num_indices);
return array;
}
void append_array(Array *array, int item) {
array->len ;
if (array->len == array->size){
array->size *= 2;
void *pointer;
pointer = realloc(array->array, array->size * array->elem);
if (pointer == NULL) {
printf("Unable to reallocate memory, exiting.\n");
free(pointer);
exit(0);
}
else {
array->array = pointer;
((int *)array->array)[array->len - 1] = item;
}
}
else
((int *)array->array)[array->len - 1] = item;
}
主程式
#include <stdio.h>
#include <stdlib.h>
#include "array.h"
int main(int argc, char** argv)
{
int i, j;
size_t indices = 20;
Array pointers = int_array(sizeof(int), indices);
for (i = 0; i < 50; i )
{
append_int_array(&pointers, i);
}
for (i = 0; i < pointers.len; i )
{
printf("Value: %d Size:%zu \n",((int *) pointers.array)[i], pointers.len);
}
return (EXIT_SUCCESS);
}
uj5u.com熱心網友回復:
我將從查看append_array. void不是一個完整的型別,這意味著你不能通過void值傳入物件。您可以通過參考傳遞它們,void *也可以參考任何其他型別:
void append_array(Array *array, void *item) {
現在,您假設您正在傳遞單個元素。但為什么要停在那里?您可以使您的函式簽名如下所示:
void append_array(Array *array, void *items, size_t count) {
這里需要額外注意的是,這array->size * 2可能不足以保存附加的資料。你可以(array->len count) * 2改用。
假設它array->size足夠大,您可以直接使用memcpy和強制轉換來復制元素 to char *,標準保證具有 size-1 元素:
memcpy((char *)array->array array->len * array->elem, items, count * array->elem);
請注意,我array->len在這里使用了索引。那是因為我的下一個建議是array->len僅在您制作副本后才增加。這將使您的尺寸檢查更簡單,并且不會像現在一樣使用一個備用元素進行重新分配。請記住,這array->len不僅是陣列的大小,也是您要附加到的從零開始的索引。
if (array->len count > array->size) {
對于單個元素,條件是
if (array->len >= array->size) {
最后,我強烈建議您回傳一個整數錯誤代碼而不是退出。此函式的用戶應該期望至少能夠在記憶體錯誤的情況下進行清理,或者可能釋放快取元素,而不是單方面崩潰。
這是最終功能的樣子:
int append_array(Array *array, void *items, size_t count)
{
if (array->len count > array->size) {
size_t size = (array->len count) * 2;
void *pointer = realloc(array->array, size * array->elem);
if (pointer == NULL) {
return 0;
}
array->array = pointer;
array->size = size;
}
memcpy((char *)array->array array->len * array->elem, items, count * array->elem);
array->len = count;
return 1;
}
以這種方式撰寫函式有一個小缺點:因為右值沒有地址,所以不能呼叫
append_array(&array, &3, 1);
You can work around this in two ways.
Make a temporary variable or buffer to hold the value:
int tmp = 3; append_array(&array, &tmp, 1);Make a type-specific wrapper that can accept elements for complete types. This works because C is purely pass-by-value (i.e., copy), so you can do
int append_int(Array *array, int value) { return append_array(array, &value, 1); }In this case, you are effectively using a new stack frame to hold the value of
tmpin the first example.
uj5u.com熱心網友回復:
該型別void是不完整的型別,無法完成,因此您不能對其進行賦值,也不能將其用作陣列引數型別。
您可以做的是append_array將 avoid *作為指向要添加的資料的引數進行更改。然后將資料指標轉換為,char *以便您可以進行單位元組指標算術以獲得正確的偏移量,然后用于memcpy復制資料。
void append_array(Array *array, void *item) {
array->len ;
if (array->len == array->size){
array->size *= 2;
void *pointer;
pointer = realloc(array->array, array->size * array->elem);
if (pointer == NULL) {
printf("Unable to reallocate memory, exiting.\n");
free(array->array);
exit(0);
}
else {
array->array = pointer;
}
}
char *p = (char *)array->array (array->len - 1) * array->elem;
memcpy(p, item, array->elem);
}
您將無法通過傳遞要添加的整數文字來呼叫此函式,但您可以使用復合文字的地址。
append_array(array, &(int){ 3 });
uj5u.com熱心網友回復:
它應該是這樣的,或者你可以typeof用來改進它。或者,使用 void **array;
#include <assert.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
void *array;
size_t size;
size_t capacity;
int elem_size;
} Array;
void initiate_array(Array *array, size_t num_indices);
Array init_array(int size, size_t num_indices);
void append_array(Array *array, void *item);
void initiate_array(Array *array, size_t num_indices) {
void *pointer;
pointer = malloc(num_indices * array->elem_size);
if (pointer == NULL) {
printf("Unable to allocate memory, exiting.\n");
// free(pointer);
exit(0);
} else {
array->array = pointer;
array->size = 0;
array->capacity = num_indices;
}
}
Array init_array(int elem_size, size_t num_indices) {
Array array;
array.elem_size = elem_size;
initiate_array(&array, num_indices);
return array;
}
void append_array(Array *array, void *item) {
if (array->size == array->capacity) {
// extend the array
}
memcpy(array->array array->size * array->elem_size, item,
array->elem_size);
array->size ;
}
int main(void) {
Array arr = init_array(sizeof(int), 10);
int item = 1;
append_array(&arr, &item);
item = 2;
append_array(&arr, &item);
item = 3;
append_array(&arr, &item);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/450300.html
上一篇:C 嵌套映射:訪問內部映射
