在 C 中使用三元运算符时,char * 和 const char * 是否兼容?

Are char * and const char * compatible when using ternary operator in C?

我从下面的代码中得到一个错误。我用gcc6.3.0编译的。

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

#define MAXLINES 5000
char *lineptr[MAXLINES];

int readlines(char *lineptr[], int nlines);
void writelines(char *lineptr[], int nlines);

void myqsort(void *lineptr[], int left, int right, 
           int (*comp)(void *, void *));

int numcmp(char *, char *);

int main(int argc, char *argv[])
{
    int nlines;
    int numeric = 0;

    if (argc > 1 && strcmp(argv[1], "-n") == 0)
        numeric = 1;
    if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
        myqsort((void **) lineptr, 0, nlines-1,
            (int (*)(void*, void*))(numeric ? numcmp : strcmp));
        writelines(lineptr, nlines);
        return 0;
    } else {
        printf("input too big to sort\n");
        return 1;
    }
}
warning: pointer type mismatch in conditional expression
    (int (*)(void*, void*))(numeric ? numcmp : strcmp));
                                             ^

下面是numcmpstrcmp两个函数的原型。

int numcmp(char *, char *);
int strcmp(const char *, const char *);

在此post中,一位回答者说他们不兼容。但是 n1256 6.5.15 p3 说(用我的粗体)

One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object or incomplete type and the other is a pointer to a qualified or unqualified version of void.

它们不兼容但符合标准的约束。但是为什么编译器会给出错误信息呢?我应该将 int numcmp(char *, char *); 转换为 int numcmp(const char *, const char *); 以便使用三元运算符吗?

They aren't compatible but meet the standard's constraint.

我认为他们不会。

numcmpint (*)(char *, char *) 类型,而 strcmpint (*)(const char *, const char *) 类型。所以一个是指向int (char *, char *)的指针,另一个是指向int (const char *, const char *)的指针。 int (char *, char *)int (const char *, const char *) 类型都不合格;事实上,函数类型不可能被限定(6.7.3 (8))。那将类似于 const function returning int 并且函数不可能是 const.

所以我们要问 int (char *, char *)int (const char *, const char *) 是否兼容类型。它们都是函数类型所以我们检查 6.7.5.3 (15):

For two function types to be compatible, both shall specify compatible return types.

好的,intint是兼容的,因为它们是相同的类型(6.2.7(1))。

Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types.

好吧,那我们得看看char *const char *是不是兼容类型。它们是指针类型所以我们检查 6.7.5.1 (2).

For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.

这两种类型都不合格。 (char * constconst 限定的,但 const char * 不是。)一个是指向 char 的指针,另一个是指向 const char 的指针。所以我们要找出 charconst char 是否兼容类型。后者是合格的所以我们检查6.7.3(9):

For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.

糟糕。 charchar 是兼容类型,但是 charconst char 不是完全相同的,所以它们不兼容。