如何在c qsort函数(数组是指针数组)中修复“ discard const”,可能与对指针的理解有关

时间:2019-02-07 23:05:43

标签: c pointers compiler-errors

此刻我正在学习C。当前正在学习c指针(指针数组)。下面的代码(简而言之,是C语言的原型)试图做的是逐行从stdin中读取文本。每个数组元素都是一个指向一行文本的指针,然后通过仅对指针进行排序来对文本进行排序。当我尝试编译代码时,编译器(gcc)发出警告“ discard const”,我尝试在str_compare函数中添加强制类型转换(const char **),但仍然无法解决我的问题

我认为这可能与我对c指针的理解有关。有人可以帮助指出我在哪里做错了吗,请问我的代码有什么问题?

我打开了许多警告标志,并将所有警告视为gcc中的错误。 我能理解这些指针,并且之前使用过qsort,结果一切都很好。但这是我第一次将指针编码为指针。所以我想我可能对此有些误解。

// Read text line by line then sort them, use point array

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

char *getLine(void);
int str_compare(const void *, const void *);

#define NLINES_MAX 1000
char *linePtr[NLINES_MAX];

int main()
{
    // Read lines;
    int long unsigned n = 0;
    for ( ; n < NLINES_MAX && (linePtr[n] = getLine()) != NULL; ++n)
        ;

    if ( !feof(stdin))
    {
        if (n == NLINES_MAX)
            fputs("sorttex: too many lines.\n", stderr);
        else
        {
            fputs ("sorttext: error reading from stdin.\n", stderr);
        }
    }
    else
    {
        qsort(linePtr, n, sizeof(char *), str_compare);
        for ( char **p = linePtr; p < linePtr +n; ++p)
            puts(*p);
    }
    return 0;
}

int str_compare(const void *p1, const void *p2)
{
    return strcmp(*(const char **)p1, *(const char **)p2);
}

#define LEN_MAX 512

char *getLine()
{
    char buffer[LEN_MAX], *lineP = NULL;
    if (fgets (buffer, LEN_MAX, stdin) != NULL)
    {
        size_t len = strlen(buffer);
        if (buffer[len-1] =='\n')
            buffer[len-1] = '\0';
        else
        {
            ++len;
        }
        if ((lineP = malloc(len)) != NULL)
            strcpy( lineP, buffer);
    }
    return lineP;
}

gcc标志为:

-std=c11 -pedantic-errors -pipe -O2 -Wall -Werror -Wextra -Wfloat-equal \
-Wshadow -Wpointer-arith -Wcast-align -Wstrict-overflow=5 -Wwrite-strings \
-Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wconversion \
-Wunreachable-code -Winit-self -march=native

我希望摆脱“丢弃常量”警告消息

2 个答案:

答案 0 :(得分:3)

传递给str_compare函数的参数是数组元素的地址。数组元素的类型为char *,并且str_compare的调用者会将其视为const,然后将其传入地址。因此,您实际上将收到一个char * const *

所以const void *实际上是

  

指向char常量指针的指针

而不是

  

指向常数char的指针

就像您编码一样。

int str_compare(const void *p1, const void *p2)
{
    char * const *pp1 = p1;
    char * const *pp2 = p2;
    return strcmp(*pp1, *pp2);
}

答案 1 :(得分:2)

该行可能是:

return strcmp(*(char *const *)p1, *(char *const *)p2);

要排序的项目是指向char *的指针(而不是您的代码所说的指向const char *的指针)。内部的const是为了确保比较功能不会修改要比较的对象(它们是char *对象,因此是char * const)。

当然,用jxh所示的额外变量扩展它也不是坏主意。