在c中,如果我有char * const *指针,我如何访问每个元素?

时间:2017-07-25 23:44:26

标签: c pointers strcmp qsort

这是针对qsort比较函数的,

int cmp(const void *p, const void *q) {
    char *const* pp = p;
    char *const* qq = q;
    ...
}

我想比较两个字符串的元素。我试过(* pp)[i]因为* pp是p,但它似乎不起作用。另外,以这种方式捕获p和q的优点是什么,而不是仅创建两个const char *?

最后但并非最不重要,我有另一个应该跳过前导空格的比较函数

int wcmp(const void *p, const void *q) {

    const char *pp = p;
    const char *qq = q;
    size_t i = 0;
    size_t j = 0;

    while(isspace(*(pp+i))) {
        i++;
    }

    while(isspace(*(qq)+j)) {
        j++;
    }

    return strcmp(pp+i, qq+j);
}

但是当我用

进行测试时
    d afdsa
   hello
  heal

输出

  heal
    d afdsa
   hello

" d afdsa"正在发生什么在中间?

1 个答案:

答案 0 :(得分:4)

qsort适用于任何大小的元素。它可以工作的唯一方法是将指针传递给元素的第一个字节,它们的类型为const void *

因此,如果你有一个int的数组,比较函数得到2个指向void的指针,它实际上指向数组中的2 int s,你比较指向的对象:

int cmp(const void *p, const void *q) {
    int *pp = p;
    int *qq = q;
    return *pp - *qq; // for example, ignoring all possible UB and such.
}

同样,如果你有一个指向char 的指针数组,即char *array[],那么每个元素都是一个指向char的指针,而比较函数则通过2个参数传递:指向const void指向这些元素。当你把它们抛回来时,你得到:

char *const *pp = p;

即。指向char的常量指针的指针。您必须比较的实际对象是指向的指向

这就是你wcmp无效的原因:

int wcmp(const void *p, const void *q) {
    const char *pp = p;
    const char *qq = q;
    ...
}

如果要排序的数组中的每个元素都是char,这将是合适的。但是元素是指针到char,所以这意味着wcmp的参数(每个都指向数组中的元素)必须转换为指向指针的指针炭

int wcmp(const void *p, const void *q) {
    char *const *ptmp = p;
    char *const *qtmp = q;

然后你必须取消引用它们以获得实际指向char

的指针
    char *pp = *ptmp; // dereference them
    char *qq = *qtmp; 

或者,您可以将这两个缩短为:

    char *pp = *(char *const *)p;
    char *qq = *(char *const *)q;

至于wcmp的其余部分,那不是真正的C - 真正的C程序员喜欢改变指针:

    while(isspace(*pp)) {
        pp ++;
    }

    while(isspace(*qq)) {
        qq ++;
    }

    return strcmp(pp, qq);
}

也就是说,只要pp指向空格字符,就增加pp,使其指向下一个字符;并为qq执行相同的操作,然后比较ppqq指向其首字符的字符串。