【问题标题】:Are char * and const char * compatible when using ternary operator in C?在 C 中使用三元运算符时,char * 和 const char * 是否兼容?
【发布时间】:2021-07-03 22:24:42
【问题描述】:

我从以下代码中得到一个错误。我用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 这么说(用我的粗体字)

第二个和第三个操作数应满足以下条件之一:
— 两个操作数都有算术类型;
— 两个操作数具有相同的结构或联合类型;
— 两个操作数都有 void 类型;
— 两个操作数都是指向兼容类型的合格或不合格版本的指针;
— 一个操作数是指针,另一个是空指针常量;或
— 一个操作数是指向对象或不完整类型的指针,另一个是指向对象的指针 void 的合格或不合格版本。

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

【问题讨论】:

  • 我不知道这种特殊情况的规则,也不是一个方便的编译器,但值得让 numcmp 使用 const char 指针 无论如何 来实现 a) 更多有用并且 b) 更好地传达其不修改其参数所指向的字符串的意图。它可能很好用,你为什么不试试呢?
  • @nanofarad 我正在解决我的 C 书中的一个练习,并且该函数是以这种形式编写的。我同意你的想法,但我只是好奇为什么我的 gcc 会抱怨该消息。
  • 如果两个操作数的类型为char *const char *,您的逻辑将适用。但它们的类型是 int (*)(char *, char *)int (*)(const char *, const char *),它们是指向两种不同类型的非限定指针。
  • 您可以通读标准中的定义以说服自己“函数返回int 并采用两个char * 参数”和“函数返回int 并采用两个const char * 参数" 是不兼容的类型。归根结底,const charchar 不是兼容的类型,因为它们的条件不同:6.7.3 (9)。

标签: c language-lawyer conditional-operator


【解决方案1】:

它们不兼容,但符合标准的约束。

我不认为他们这样做。

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):

对于要兼容的两种函数类型,两者都应指定兼容的返回类型。

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

此外,参数类型列表(如果两者都存在)应在参数数量和省略号终止符的使用方面达成一致;对应的参数应该有兼容的类型。

好的,所以我们必须找出char *const char * 是否是兼容的类型。它们是指针类型,所以我们检查 6.7.5.1 (2)。

为了使两种指针类型兼容,两者都应具有相同的限定,并且都应 是指向兼容类型的指针。

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

为了使两个合格的类型兼容,两者都应具有相同的合格版本 兼容类型;说明符或限定符列表中类型限定符的顺序 不影响指定类型。

哎呀。 charchar 是兼容的类型,但 charconst char 的限定不同,因此它们不兼容。

【讨论】:

    猜你喜欢
    • 2013-04-17
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2022-01-15
    • 2022-08-11
    • 2011-08-27
    相关资源
    最近更新 更多