Malloc,Realloc,Memset:struct指针,char数组,int

时间:2015-04-27 13:35:36

标签: c pointers char malloc realloc

#ifndef vECTOR_h
#define vECTOR_h

#include<string.h>
#include<stdio.h>
#include<stdlib.h>

/* My iterator is an int but thanks to this typedef I could change it easily */
typedef int iterator;
#define iterator_begin 0
#define iterator_end -1

//typedef is for vector_type and in the meanwhile struct vector_struct is defined 
typedef struct vector_struct {
    size_t e_sz; //size of a single element in e_array in bytes, size_t is always unigned and machine/compiler bounded usually undsinged long
    char e_type; //type of a single element in e_array used rarely since we go with void pointers

     #define V_INT 1
     #define V_DOUBLE 2
     #define V_CHAR 3
     #define V_FLOAT 4

    unsigned no_e;  //number of elements in e_array with a value , unsigned    alone means unsigned int
    unsigned cur_cap; //max capacity of e_array at that moment
    void* e_array;  //real data
}* vector_type;

#define vector_size(v) ((v)->no_e)
#define vector_capacity(v) ((v)->cur_cap)
#define vector_int_at(v,i) (*((int*)v_at(v,i)))
#define vector_double_at(v,i) (*((double*)v_at(v,i)))
#define vector_char_at(v,i) (*((char*)v_at(v,i)))
#define vector_string(v) ((char*)v_at(v,0))
#define vector_float_at(v,i) (*((float*)v_at(v,i)))
//not necessary defines

 //Allocate space for a vector struct and initialize some elements 
vector_type v_create_empty(char type){ 
    vector_type my_v = (vector_type)check_a(malloc(sizeof(struct vector_struct)));

//since it's used only here we could drop type and receive size direclty where in vector.h we #define V_INT_S sizeof(int)
//on the other hand a better typed implementation would do a large use of e_type, less void pointer and more typed casts
    my_v->e_sz = (type == V_INT ? sizeof(int) : type == V_DOUBLE ? sizeof(double) : type == V_FLOAT ? sizeof(float) : 1); //1 for default is char then sizeof(char)

    my_v->e_type = type;
    my_v->no_e = my_v->cur_cap = 0;
    my_v->e_array = NULL;
    return my_v;
}

void* v_at(vector_type v, iterator i){
    if ( v == NULL )
        fail("v_at() Error: no such vector");
    if ( i == iterator_end )
        i = v->no_e -1;
    if ( i < 0 || i >= v->no_e )
        fail("v_at() Error: no such element in this vector");

    return (void*)((char*)v->e_array + (i * v->e_sz)) ;  //i sum char to char  
//in order to get the specified position of variable type casting to void*  for the return value
//
//typed alternative solution
//
//    switch(v->type)
//    {
//    case V_INT:
//         return ((void*)((int*)v->e_array) + i) ;
//          break;
//    case V_DOUBLE:
//         return ((void*)((double*)v->e_array) + i) ;
//          break;
//    case V_FLOAT:
//        return ((void*)((float*)v->e_array) + i) ;
//          break;
//    default:
//         return ((void*)((char*)v->e_array) + i) ;
//          break;
//    }
}

//Function to push some elements back to the first v->e_array void pointer and so on
void v_push_back(vector_type v, void* new_val){
    if ( v->no_e >= v->cur_cap ) {
        /*** reallocate a larger array ***/
        v->cur_cap += (v->cur_cap)? v->cur_cap : 2; 
        //add 2 elements if v->cur_cap is 0

        //if that's first call malloc will be used
        void *ptr = realloc(v->e_array,v->cur_cap * v->e_sz);
        if (ptr == NULL)
        {
            ptr = check_a(malloc(v->cur_cap * v->e_sz));
            memcpy(ptr, v->e_array ,v->no_e * v->e_sz);
            free(v->e_array);
            v->e_array = ptr;
        }
    v->e_array = check_a(realloc(v->e_array,v->cur_cap * v->e_sz));  
    //v->cur_cap * v->e_sz is never 0
    }
   /*** copy new_val in the array at index v->no_e ***/
     v->e_array = check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) , new_val, v->e_sz));    

    (v->no_e)++;
}

// v_push_back FUNCTION CALLED LIKE THIS from main in another c file: 
// the purpose is to link all characters in an array of characters
c1 = 'c'; v_push_back(vc1,(void*)&c1);
c1 = 'i'; v_push_back(vc1,(void*)&c1);
c1 = 'a'; v_push_back(vc1,(void*)&c1);
c1 = 'o'; v_push_back(vc1,(void*)&c1);
c1 = 0; v_push_back(vc1,(void*)&c1);

printf("Vector vc1 now contains %d characters (capacity=%d): %s\n",
       vector_size(vc1)/**((v)->no_e)**/,vector_capacity(vc1)/** ((v)->cur_cap)**/,vector_string(vc1))/** ((char*)v_at(v,0))**/; // ==>ERROR DOESN 'T PRINT THE %s of (char*)v_at(v,0)

我不能打印通过推回数组列表的元素创建的字符串的值,在调试期间没有分段错误,你有时会读取函数check_a(指针*)它只包含一个控制一个NULL指针,每次在malloc,realloc ...命令

之后调用

许多代码丢失但是这里是有缺陷的部分 这是一个应该实现float,int等数组的程序;因此,为了保持通用性,有时需要转换为void *,有时会转换为char *以逐字节移动。

1 个答案:

答案 0 :(得分:0)

v_push_back实现出错:

v->e_array = check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) ,new_val, v->e_sz)); //pointer has not to be saved

 check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) ,new_val, v->e_sz));

因为memcpy返回一个指针,在这种情况下,返回到数组的最后一个元素,所以我们将失去对所有先前内存的访问权