简体   繁体   中英

is it possible to copy an array to a different type of another array in c using generic function

is it possible to copy an array to a different type of another array in c using generic function, a function takes generic types. So I could use it to copy an array to a different type of another array like: ( int to double), ( float to int ) or ( float to double), in the same time I could still use it to copy an array to the same type of another array like: ( int to int ) or ( double to double), so is it possible to write a generic function could do all that.

i implemented it in c preprocessor, but not what i actually need :

#define CAST(VAR) __typeof__(VAR) 

#define ARRAY_COPY(src, dest, SIZ) do{     \
    for(size_t I = 0; I < SIZ; I++){       \
      dest[I] = (CAST(*dest)) src[I];      \
    }                                      \
  } while(0)

but i still need to implement it in a generic function, so is it possible ?

Your question is not really Array Copy, its more like array conversation. Nonetheless, after digging around for generic functions, I wrote this simple code. The code is pretty straight forward and easy to understand.

It just use the _Generic to look at src and dest. If src is and int * and dest is a double pointer then it will call the arrInt2Double function. Of which had 3 lines of code and can be compressed down to 1 lines if you don't need the return status code.

I wrote 2 functions for you, 1 is double to int and 1 is int to double. If either the type of src and dest is unsupported it will call a function to return a status code 1. Status code 0 will be returned if the type that inputted was supported else it is a 1.

Also, you can look at here to understand more about _Generic usage. C11 _Generic usage , and here https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.cbclx01/genericselection.htm .

But in case if I did not understand you correctly and you wanted to just use an ordinary function to do that for you. But the function can take in generic types. I wrote an example 2. You can pass any type using the void pointer. But you still somehow need to know the type to actually work with it. With mem copy it is easy but you would still need to pass the total byte sizes(len * bytes perIndex). It is a bit harder with type converting. You still have to somehow pass the function the type of arrays.

For the second example, I wrote a small function that can convert int to double and double to int. You just have to figure out how to pass the type and what id to use for each type.

But ultimately, these below are optional methods, the original method that you use to define a macro like that beat all the methods below. In term of why to use, I don't see any point. In term of seeing the alternative, below are the alternatives.

Example 1

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

int arrInt2Double(int *, double *, size_t);
int arrDouble2Int(double *, int *, size_t);
int arrConv2Fail(void *, void *, size_t);

#define arrConv2(src, dest, len) \
    _Generic((src), \
        int *:     _Generic((dest), \
                        double * : arrInt2Double, \
                        default: arrConv2Fail \
                    ), \
        double *:        _Generic((dest), \
                        int * : arrDouble2Int , \
                        default: arrConv2Fail \
                    ), \
        default: arrConv2Fail \
    ) (src, dest, len)

int arrConv2Fail(void * a, void * b, size_t len){ return 1; }

int arrInt2Double(int * src, double * dest, size_t len){
  for (size_t i = 0; i < len; i++)
    dest[i] = (double) src[i];
  return 0;
}

int arrDouble2Int(double * src, int * dest, size_t len){
  for (size_t i = 0; i < len; i++)
    dest[i] = (int) src[i];
  return 0;
}

int main() {
    const size_t size = 10;
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double b[size] = { 0 };
    char c[size];

    // Convert int to double
    printf("Status Code: %d\n", arrConv2(a, b, size)) ;

    for (size_t i = 0; i < size; i++){
      printf("b[%zu] : %lf\n", i, b[i]);
      // times 2 for later test
      b[i] = b[i] * 2;
    };

    puts("");
    puts("");

    // Convert double to int;
    printf("Status Code: %d\n", arrConv2(b, a, size)) ;
    for (size_t i = 0; i < size; i++){
      printf("a[%zu] : %d\n", i, a[i]);
    };

    puts("");
    puts("");

    // Unsupport type.
    printf("Unsupport type Status Code: %d\n", arrConv2(c, a, size)); 

    return 0;
}

Example 2:

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

int arrConv(void * src, void * dst, int srcType, int destType, size_t len){
  // 1 == int
  // 2 == double
  // int 2 double
  if ( srcType == 1 && destType == 2 ){
    for (size_t i = 0; i < len; i++)
      ((double *)dst)[i] = (double)((int *)src)[i];

  // double to int 
  } else if ( srcType == 2 && destType == 1 ){
    for (size_t i = 0; i < len; i++)
      ((int *)dst)[i] = (int)((double *)src)[i];
  } else{
    return 1;
  }
  return 0;
};

int main() {
    const size_t size = 10;
    int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    double b[size] = { 0 };
    char c[size];

    // Convert int to double
    printf("Status Code: %d\n", arrConv(a, b, 1, 2, size)) ;

    for (size_t i = 0; i < size; i++){
      printf("b[%zu] : %lf\n", i, b[i]);
      // times 2 for later test
      b[i] = b[i] * 2;
    };

    puts("");
    puts("");

    // Convert double to int;
    printf("Status Code: %d\n", arrConv(b, a, 2, 1, size)) ;
    for (size_t i = 0; i < size; i++){
      printf("a[%zu] : %d\n", i, a[i]);
    };

    puts("");
    puts("");

    // Unsupport type.
    printf("Unsupport type Status Code: %d\n", arrConv(b, c, 1, 3, size)); 

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM