c에서 벡터를 복제하는 방법?
c++ 및 벡터/리스트 이전에는 데이터를 더 많이 저장할 필요가 있을 때 어레이 크기를 어떻게 확장했습니까?
벡터와 리스트는 개념적으로 C++와 연결되어 있지 않습니다.유사한 구조를 C에 구현할 수 있지만 구문(및 오류 처리)만 다를 뿐입니다.예를 들어 LodePNG는 std:: vector와 매우 유사한 기능을 가진 동적 배열을 구현합니다.사용 예시는 다음과 같습니다.
uivector v = {};
uivector_push_back(&v, 1);
uivector_push_back(&v, 42);
for(size_t i = 0; i < v.size; ++i)
printf("%d\n", v.data[i]);
uivector_cleanup(&v);
보다시피 사용법이 다소 상세하고 다양한 유형을 지원하려면 코드를 복제해야 합니다.
nothings/stb는 다음과 같은 모든 유형에서 사용할 수 있는 간단한 구현을 제공합니다.
double *v = 0;
arrpush(v, 1.0);
arrpush(v, 42.0);
for(int i = 0; i < arrlen(v); ++i)
printf("%g\n", v[i]);
arrfree(v);
또한 해시 맵을 제공하고 C의 타입 세이프 컨테이너에 사용하는 트릭을 다른 범용 컨테이너에도 적용할 수 있습니다.
중 로 기본 할 수 .realloc
) ( ( )를 사용하여 새 합니다.malloc
free
정도, 즉 --어느 , 즉 --어느 정도라고 할 수 있습니다.std::vector
C++로 하다
그러나 많은 C코드는 재할당을 통해 메모리를 직접 관리하는 데 의존합니다.
void* newMem = realloc(oldMem, newSize);
if(!newMem) {
// handle error
}
oldMem = newMem;
:realloc
에러가 발생했을 경우 null을 반환하지만 오래된 메모리는 여전히 유효합니다.이러한 상황에서는, 이 일반적인(잘못된) 사용으로 메모리가 누설됩니다.
oldMem = realloc(oldMem, newSize);
if(!oldMem) {
// handle error
}
std::vector
, 한 C 등가물, C 등가물, C 등입니다.realloc
은 O보증을 .realloc
메모리 이동을 회피하는 것이 효율적일 수 있습니다.
많은 C프로젝트가 벡터형 API를 구현하게 됩니다.동적 어레이는 일반적인 요구이기 때문에 메모리 관리를 가능한 한 추상화하는 것이 좋습니다.일반적인 C 실장은 다음과 같습니다.
typedef struct dynamic_array_struct
{
int* data;
size_t capacity; /* total capacity */
size_t size; /* number of elements in vector */
} vector;
API에서 입니다.vector
:
int vector_init(vector* v, size_t init_capacity)
{
v->data = malloc(init_capacity * sizeof(int));
if (!v->data) return -1;
v->size = 0;
v->capacity = init_capacity;
return 0; /* success */
}
이 은 하죠.push_back
,insert
,resize
, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,realloc
size
넘다를 넘다capacity
vector_resize(vector* v, size_t new_size);
vector_push_back(vector* v, int element);
" " " 입니다.capacity
는 항상 재할당을 피하기 위해 2배가 됩니다.은 보통 .std::vector
인 경우는 )std::vector
하지 않다realloc
C++ 오파파 / C++ c c c c c c c c c 。오려 rather rather rather.std::vector
새 버퍼를 할당한 후 구성/이동 개체를 복사할 수 있습니다(배치 사용).new
)를 새로운 버퍼에 넣습니다.
C에서의 실제 벡터 구현에서는void*
포인터보다 요소로서의 포인터int
그래서 코드가 더 일반적입니다.어쨌든, 이러한 것은 많은 C프로젝트에 실장되어 있습니다.C에서의 벡터 실장의 예에 대해서는, http://codingrecipes.com/implementation-of-a-vector-data-structure-in-c 를 참조해 주세요.
우선 구현에 필요한 구성원을 보유하는 구조를 숨김으로써 시작합니다.그런 다음 구조의 내용을 조작하는 기능 그룹을 제공합니다.
다음과 같은 경우:
typedef struct vec
{
unsigned char* _mem;
unsigned long _elems;
unsigned long _elemsize;
unsigned long _capelems;
unsigned long _reserve;
};
vec* vec_new(unsigned long elemsize)
{
vec* pvec = (vec*)malloc(sizeof(vec));
pvec->_reserve = 10;
pvec->_capelems = pvec->_reserve;
pvec->_elemsize = elemsize;
pvec->_elems = 0;
pvec->_mem = (unsigned char*)malloc(pvec->_capelems * pvec->_elemsize);
return pvec;
}
void vec_delete(vec* pvec)
{
free(pvec->_mem);
free(pvec);
}
void vec_grow(vec* pvec)
{
unsigned char* mem = (unsigned char*)malloc((pvec->_capelems + pvec->_reserve) * pvec->_elemsize);
memcpy(mem, pvec->_mem, pvec->_elems * pvec->_elemsize);
free(pvec->_mem);
pvec->_mem = mem;
pvec->_capelems += pvec->_reserve;
}
void vec_push_back(vec* pvec, void* data, unsigned long elemsize)
{
assert(elemsize == pvec->_elemsize);
if (pvec->_elems == pvec->_capelems) {
vec_grow(pvec);
}
memcpy(pvec->_mem + (pvec->_elems * pvec->_elemsize), (unsigned char*)data, pvec->_elemsize);
pvec->_elems++;
}
unsigned long vec_length(vec* pvec)
{
return pvec->_elems;
}
void* vec_get(vec* pvec, unsigned long index)
{
assert(index < pvec->_elems);
return (void*)(pvec->_mem + (index * pvec->_elemsize));
}
void vec_copy_item(vec* pvec, void* dest, unsigned long index)
{
memcpy(dest, vec_get(pvec, index), pvec->_elemsize);
}
void playwithvec()
{
vec* pvec = vec_new(sizeof(int));
for (int val = 0; val < 1000; val += 10) {
vec_push_back(pvec, &val, sizeof(val));
}
for (unsigned long index = (int)vec_length(pvec) - 1; (int)index >= 0; index--) {
int val;
vec_copy_item(pvec, &val, index);
printf("vec(%d) = %d\n", index, val);
}
vec_delete(pvec);
}
또한 함수 그룹의 vec* 대신 void*를 사용하여 캡슐화를 실현하고 헤더가 아닌 함수 그룹을 포함하는 C 모듈 내에서 구조 정의를 정의함으로써 사용자에게 구조 정의를 숨깁니다.또한, 헤더에서 제외되고 단순히 C 모듈에서만 프로토타입화함으로써 비공개라고 생각되는 기능을 숨깁니다.
구현 vc_vector를 볼 수 있습니다.
struct vc_vector {
size_t count;
size_t element_size;
size_t reserved_size;
char* data;
vc_vector_deleter* deleter;
};
...
vc_vector* vc_vector_create_copy(const vc_vector* vector) {
vc_vector* new_vector = vc_vector_create(vector->reserved_size / vector->count,
vector->element_size,
vector->deleter);
if (unlikely(!new_vector)) {
return new_vector;
}
if (memcpy(vector->data,
new_vector->data,
new_vector->element_size * vector->count) == NULL) {
vc_vector_release(new_vector);
new_vector = NULL;
return new_vector;
}
new_vector->count = vector->count;
return new_vector;
}
사용방법:
vc_vector* v1 = vc_vector_create(0, sizeof(int), NULL);
for (int i = 0; i < 10; ++i) {
vc_vector_push_back(v1, &i);
}
// v1 = 0 1 2 3 4 5 6 7 8 9
vc_vector* v2 = vc_vector_create_copy(v1);
// v2 = 0 1 2 3 4 5 6 7 8 9 (copy of v1)
// to get pointer to int:
const int* v2_data = vc_vector_data(v1);
https://github.com/jakubgorny47/baku-code/tree/master/c_vector
제 실장은 이렇습니다.데이터 포인터, 크기(요소 단위), 전체 할당된 공간 및 void 포인터를 사용할 수 있도록 벡터에 저장되는 유형의 크기를 포함하는 구조체입니다.
Gena 라이브러리를 사용할 수 있습니다.흡사하다stl::vector
순수한 C89로.
README의 특징은 다음과 같습니다.
- 플레인 C 어레이와 마찬가지로 액세스 벡터 요소:
vec[k][j]
; - 다차원 어레이가 있다.
- 벡터 복사
- 벡터가 필요할 때마다 이 작업을 수행하는 것이 아니라 필요한 벡터 유형을 별도의 모듈에서 한 번 인스턴스화합니다.
- 값을 벡터에 전달하는 방법과 벡터에서 값을 반환하는 방법(값별 또는 포인터별)을 선택할 수 있습니다.
여기서 확인하실 수 있습니다.
https://github.com/cher-nov/Gena
언급URL : https://stackoverflow.com/questions/4694401/how-to-replicate-vector-in-c
'programing' 카테고리의 다른 글
형식 설명 2.6.1에서 vue js @Component를 사용하는 방법은 무엇입니까? (0) | 2022.07.29 |
---|---|
디렉토리가 있는지 확인하는 휴대용 방법 [Windows/Linux, C] (0) | 2022.07.29 |
왜 소수의 비디오 게임만 자바어로 쓰여져 있는 거죠? (0) | 2022.07.28 |
Vue 3 Modal이 다시 열 때 이전 데이터를 가지고 돌아오다 (0) | 2022.07.28 |
C코드로 ":-!"가 뭐죠? (0) | 2022.07.28 |