C指针解除引用错误

时间:2017-08-18 03:12:08

标签: c arrays pointers compiler-errors

假设我有以下代码(示例):

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

void Ex(void *ret, int ret_len, int choice){
    if(choice==1){
        int *ret = ret;              
        for(int i=0; i<ret_len; i++){
            *(ret+i) = i;
        }
     } else {
        int **ret = ret;            
        for(int i=0; i<ret_len; i++){
            for(int j=0; j<ret_len; j++){
                *(*(ret+i)+j) = i*j;
            }
        }
     }
}

int main()
{
    int m[10];
    Ex(m,10,1);
    printf("%i",m[3]);
    return 0;
}

该函数的目标是获取指向一个二维数组的预分配内存的指针。

编译和执行时,代码在choice==1时有效,否则,如果我运行

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

void Ex(void *ret, int ret_len, int choice){
    if(choice==1){
        int *ret = ret;              
        for(int i=0; i<ret_len; i++){
            *(ret+i) = i;
        }
     } else {
        int **ret = ret;            
        for(int i=0; i<ret_len; i++){
            for(int j=0; j<ret_len; j++){
                *(*(ret+i)+j) = i*j;
            }
        }
     }
}

int main()
{
    int m[100];
    Ex(m,10,2);
    printf("%i", m[3][5]);
    return 0;
}

没有产生任何输出,代码似乎永远运行(注意选择现在不是1而m是正确的大小)

我的印象是,Ex中的强制转换应该改变数组的形状,并允许main将其索引为它,就像它是2d一样,但是它既没有索引,也没有像1d那样工作,也没有工作。

3 个答案:

答案 0 :(得分:0)

因为ret属于int *类型,但其他部分是:

    for(int i=0; i<ret_len; i++){
        for(int j=0; j<ret_len; j++){
            *(*(ret+i)+j)=i*j;
        }
    }

需要ret类型int **。这会导致错误。

解决问题的方法是使用void *。这是在C中使用泛型的一种方法。

查看C中的qsort

void Ex(void *_ret, int ret_len, int choice){
    if(choice==1){
        int *ret = (int *)_ret;              // <---- type conversion
        for(int i=0; i<ret_len; i++){
            *(ret+i) = i;
        }
     } else {
        int **ret = (int **)_ret;            // <---- type conversion
        for(int i=0; i<ret_len; i++){
            for(int j=0; j<ret_len; j++){
                *(*(ret+i)+j) = i*j;
            }
        }
     }
}

答案 1 :(得分:0)

我提出的现有代码变化最小的最接近的事情是:

#include <stdio.h>
void Ex(int * ret, int ret_len, int choice){
    if(choice==1){
        for(int i=0; i<ret_len; i++){
            *(ret+i)=i;
        }
     }else{
        for(int i=0; i<ret_len; i++){
            for(int j=0; j<ret_len; j++){
                *(ret + i*ret_len + j) = i*j;
            }
        }
     }
}

int main() {
  int anint[10][10];
  Ex(anint, 10, 2);

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {printf("%d\n", anint[i][j]);}
  }
}

基本上,我手动操纵Ex函数中的偏移量。我假设两个维度的长度总是相同的。

更“传统的方式”是一个真正的二维数组,其中每个元素都是独立的malloc。因此,第一级数组的元素可以通过力施加到指针并在第二级中被解除引用。但我不愿意多次调用malloc。

我希望这可以解决你的问题。

答案 2 :(得分:0)

看了这个问题的评论和一些答案,这就是我为你的要求所收集的。

您需要一个通用函数,该函数采用choice维的数组并使用某些值对其进行初始化。

这可以满足您的目的。

void Ex(void *_ret, int ret_len, int choice){
    if(choice==1){
        int *ret = _ret;              
        int i;
        for(i=0; i<ret_len; i++){
            ret[i] = i;
        }
     } else {
        int (*ret)[ret_len] = _ret;            
        int i, j;
        for(i=0; i<ret_len; i++){
            for(j=0; j<ret_len; j++){
                ret[i][j] = i*j;
            }
        }
     }
}

现在你可以这样称呼它

int main(void) {
    int first[10];
    Ex(first, 10, 1);
    int second[20][20];
    Ex(second, 20, 2);
    printf("first[4] = %d\n", first[4]);
    printf("second[3][4] = %d\n", second[3][4]);
} 

您可以看到Demo here