【问题标题】:Generic array printer not working for doubles type通用数组打印机不适用于双打类型
【发布时间】:2021-03-17 16:27:33
【问题描述】:

老实说,我在这里发疯了,试图理解为什么这个通用数组打印机实现不起作用。好吧,它适用于 int 数组,但不适用于 double 数组。我在这里错过了什么?

void array_printer(FILE* stream, void* data, size_t data_type_size, size_t nr_rows, size_t nr_cols, char *format){

    size_t offset = 0;
    for (size_t r=0; r<nr_rows;++r){
        for (size_t c=0; c<nr_cols; ++c){
            fprintf(stream,format, *((int8_t*)data + offset*data_type_size));
            //fprintf(stream,format, *((char*)data + offset*data_type_size));  // same behaviour
            offset++;
        }
        fprintf(stream,"\n");
    }
}

void array_print_double_2D(FILE* stream, double* data, size_t nr_rows, size_t nr_cols){
    array_printer(stream, data, sizeof(double), nr_rows, nr_cols, " %lf ");
}

void array_print_int_2D(FILE* stream, int* data, size_t nr_rows, size_t nr_cols){
    array_printer(stream, data, sizeof(int), nr_rows, nr_cols, " %d ");
}

int main(){
    double *data_double = calloc(12, sizeof(double));
    data_double[0] = 1;
    data_double[1] = 2;
    data_double[2] = 3; 
    array_print_double_2D(stdout, data_double, 3, 4);
    /*
    0.000000  0.000000  0.000000  0.000000
    0.000000  0.000000  0.000000  0.000000         what??
    0.000000  0.000000  0.000000  0.000000
    */


    int*data_int = calloc(12, sizeof(int));
    data_int[0] = 1;
    data_int[1] = 2;
    data_int[2] = 3; 
    array_print_int_2D(stdout, data_int, 3, 4);
    /*
    1  2  3  0
    0  0  0  0               correct
    0  0  0  0
    */
    

【问题讨论】:

  • *(int8_t*)(data+...)*将*返回与 printf 说明符“%lf”不一致的int8_t
  • 尝试不适合 int8_t 的更大整数值,例如256.跨度>
  • 此外,声明`double *data_int`有点混乱。
  • 你的第二个例子应该是int *data_int吗?

标签: c


【解决方案1】:

表达式*(int8_t*)(data+...) 将返回与 printf 说明符“%lf”不一致的 int8_t。这会导致未定义的行为。

使用生成打印机的宏可以有效地解决该问题。

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


#define DEFINE_ARRAY_PRINT_2D(TYPE, FMT) \
void array_print_ ## TYPE ## _2D(FILE* stream, void* data, size_t nr_rows, size_t nr_cols) { \
    size_t offset = 0; \
    for (size_t r=0; r<nr_rows;++r){ \
        for (size_t c=0; c<nr_cols; ++c){ \
            fprintf(stream,FMT, ((TYPE*)data)[offset]); \
            offset++; \
        } \
        fprintf(stream,"\n"); \
    } \
}

// generate printers
DEFINE_ARRAY_PRINT_2D(int, " %d ")
DEFINE_ARRAY_PRINT_2D(double, " %lf ")


int main(){
    double *data_double = calloc(12, sizeof(double));
    data_double[0] = 1;
    data_double[1] = 2;
    data_double[2] = 3; 
    array_print_double_2D(stdout, data_double, 3, 4);

    int *data_int = calloc(12, sizeof(int));
    data_int[0] = 1;
    data_int[1] = 2;
    data_int[2] = 3; 
    array_print_int_2D(stdout, data_int, 3, 4);

    return 0;
}

产生输出:

 1.000000  2.000000  3.000000  0.000000 
 0.000000  0.000000  0.000000  0.000000 
 0.000000  0.000000  0.000000  0.000000 
 1  2  3  0 
 0  0  0  0 
 0  0  0  0 

正如预期的那样。

【讨论】:

    【解决方案2】:

    您将内存投射到int8_t* 并取消引用它,您期待什么?我会提供某种枚举来区分类型并在需要时转换为正确的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      相关资源
      最近更新 更多