关于在通用函数中进行转换的一些误解

时间:2018-06-16 15:13:19

标签: c casting pointer-arithmetic

我对班上的教程有些误解。有一个名为print_Arr()的函数,它是泛型函数,它获取指向double或整数数组的指针并打印它。

以下是代码:

int  main() {
    int  a[] = { 2,7,6,4,1 };
    double b[] = { 12.5,2.7,3.0,5.5,5.9,1.0 };

    print_Arr(a, sizeof(a)/sizeof(a[0]), sizeof(int), print_int);
    print_Arr(b, sizeof(b)/sizeof(b[0]), sizeof(double), print_double);
}

void print_Arr(void* a, int size, int m, void (*print_func)(void* )) {

    for (int i = 0; i <= size-1; i++)
    {
        print_func((char*)a + m*i);
    }
}

void print_int(int* p) {

    printf("%d\n", *p);
}

void print_double(double* num) {

    printf("%f\n", *num);
}

为什么我必须在此行中将a转换为(char*)

print_func((char*)a + m*i);

我向print_Arr()泛型函数发送了两种类型的数组整数或双精度数, 因此逻辑上将a投射到int *double*

但为什么它会投放到char*?我错过了什么?

4 个答案:

答案 0 :(得分:4)

首先,需要关于 为什么 的演员:

指针算法使用指向类型的大小。 void是一个永远不完整的类型,无法完成,因此在指向void类型的指针上无法进行指针运算。

为加法运算符添加引用C11,章节§6.5.6,约束:

  

另外,两个操作数都应具有算术类型,或者一个操作数应为a   指向完整对象类型的指针,另一个应具有整数类型。

,并且,从章节§6.2.5,

  

void类型包含一组空值;它是一个不完整的对象类型   无法完成。

那说,为什么演员要char*

指针算法使用指向的类型。再次引用规范

  

[...]如果表达式P指向   数组对象的i - 元素,表达式(P)+N(等效地,N+(P))和   (P)-N(其中N的值为n)分别指向i+n - 和i−n - 元素   数组对象,只要它们存在。

在这里,看看你的构造:

      ((char*)a + m*i);

其中m是实际参数指向的实际对象类型的大小。因此,如果将指针强制转换为实际类型,则计算错误。要进行比较,请说:

  • sizeof (char)为1,由标准规定。
  • sizeof (int) == 4,在您的平台上说。

因此,对于数组int arr[ ] = {1, 2, 3, 4},表达式

  • (char*)a + (sizeof(int)*1)
  • (int*) a + 1

是等价的。

最后,触及将另一种指针转换为char*并访问它的主题:

  

[...]当指向对象的指针转换为指向字符类型的指针时,   结果指向对象的最低寻址字节。连续增量   结果,直到对象的大小,产生指向对象剩余字节的指针。 [....]

答案 1 :(得分:3)

您需要char *强制转换,因为您对指针执行指针运算,从头开始获取字节偏移量,但您不能在void *上执行此操作。

答案 2 :(得分:0)

void指针没有类型大小,因此您无法使用它进行计算。

答案 3 :(得分:-1)

    public:

       int num=0;

       int c;
    int doubleToChar(double a){
       while ((a-1)>=0){
        num++;

       }
       c=a;
       return a*10;

    }/*    int doubleToCharhundred(double a){
       while ((a-1)>=0){
        num++;

       }

       return a*100-c;

    }*/
    double a=12.12345;
    char *tenDivide ;
    char *intPart;
    //u can add hundred or thousand by another char;
    tenDivide =doubleToChar(a);
    if(num<128)
      intPart=num; 
    else{
      while(num-1){
           //same  doubleToChar
       }
    }