初始化从指针目标类型中丢弃“const”限定符

initialization discards ‘const’ qualifier from pointer target type

提问人:collegecoder 提问时间:3/7/2021 最后编辑:collegecoder 更新时间:3/9/2021 访问量:2151

问:

我有一个包含字符名称的数组结构。我想使用 qsort 按字母顺序对它们进行排序,但是我不断收到一条错误消息,说“初始化从指针目标类型中丢弃'const'限定符”。我相信我的 cmpmi() 函数和 qsort 参数是正确的。任何帮助都非常感谢!

我的错误是:

gcc -std=gnu11 -Werror -Wall -o main main.c -lm -g
main.c: In function ‘compmi’:
main.c:18:25: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
  const student_t **p1 = a;
                         ^
main.c:19:25: error: initialization discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
  const student_t **p2 = b;
                         ^
cc1: all warnings being treated as errors
makefile:2: recipe for target 'main' failed
make: *** [main] Error 1

这是我的 qsort 函数:

int compmi(const void *a, const void *b)
{
    const student_t **p1 = a;
    const student_t **p2 = b;
    return strcmp((*p1)->name, (*p2)->name);
}

法典:

int main(int argc, char **argv) {
    unsigned numrecords;
    int i = 0;
    int length_multiplier = 1;
    char *lettergrade;
    //char *input = NULL;
    //char *pItem;
    
    student_t **students = NULL;
    // OPENS THE FILE IN BINARY
    FILE *input_file;
    input_file = fopen("input.bin", "rb");
    // READS THE NUMBER OF RECORDS
    fread(&numrecords, sizeof(u_int32_t), 1, input_file);
    
    // LOOPING THROUGH EACH ENTRY
    for(i = 0; i <= numrecords; i++)
    {
        // ALLOCATES MEMORY
        students = realloc(students, sizeof(student_t *) * length_multiplier);
        students[i] = malloc(sizeof(student_t));
        
        students[i]->name = malloc(sizeof(student_t)* 20);
        fread(students[i]->name, sizeof(student_t), 20, input_file);//READ NAME
        fread(&students[i]->gpa, sizeof(student_t), 1, input_file); // READ GPA
        fread(&students[i]->age, sizeof(u_int32_t), 1, input_file);// READ AGE
        
        length_multiplier++;
        
    }
    //SORTING WITH QSORT
    qsort(*students, numrecords, sizeof(student_t *), compmi);

    // PRINTING OUTPUT
    for(i = 0; i < length_multiplier - 2 ; i++)
    {
        printf("%i of %d:\n", i + 1, numrecords);
        printf("Name: %s\n", students[i]->name);
        //printf("UPDATED GPA USE THIS: %.1f\n", students[i]->gpa);
        printf("GPA:  %.1f \n", students[i]->gpa);
        printf("Age:  %i\n", students[i]->age);
        printf("\n");
    }
    
    // FREEING MEMORY
    for(i = 0; i < length_multiplier; i++)
    {
        free(students[i]);
        
    }
    free(students);
    fclose(input_file);
    
    return 0;
}
数组 c struct qsort alloc

评论

0赞 tstanisl 3/7/2021
尝试将“const student_t **”替换为 'const student_t * const *'
2赞 chqrlie 3/7/2021
@collegecoder:请不要修复问题中的代码,因为它会使评论和答案与问题不一致/
0赞 Nate Eldredge 3/7/2021
qsort(*students,...)我认为这应该只是,而不是。您希望对整个指针数组进行排序,而不是对其第一个元素指向的“数组”进行排序。students*students
0赞 David C. Rankin 3/7/2021
@rici - 我认为你是对的。需要更多的咖啡。
1赞 Nate Eldredge 3/7/2021
for(i = 0; i <= numrecords; i++):看起来像一个差一的错误,应该是。i < numrecords

答:

2赞 dbush 3/7/2021 #1

该变量指向限定类型,但不指向类型(但该类型指向的是)。您需要在 s 之间添加。aconstp1constconst*

int compmi(const void *a, const void *b)
{
    const student_t * const *p1 = a;
    const student_t * const *p2 = b;
    return strcmp((*p1)->name, (*p2)->name);
}

评论

0赞 collegecoder 3/7/2021
这修复了我的错误消息,但是当我尝试打印学生时,它们只是空的。返回条目后会发生什么情况?
0赞 CiaPan 3/8/2021
@collegecoder 按照这条评论说的去做:stackoverflow.com/questions/66510293/... 在 qsorting 之前验证您的数据是否正确读取,而不是抱怨它们不正确_after _ 某些处理。
1赞 chqrlie 3/7/2021 #2

代码中存在多个问题:

  • 比较函数将指向常量对象的指针转换为指向非恒定对象本身的指针,将指向常量对象的指针转换为常量对象。没有保留原来的恒常性。定义应为:student

    const student_t * const *p1 = a;
    const student_t * const *p2 = b;
    
  • 读取循环应该在 so you should use 而不是 .i == numrecordsi < numrecordsi <= numrecords

  • 大小不正确:应指定杆件类型的大小,而不是结构的大小。freadstudent_t

  • 你传递给而不是数组指针。*studentsqsortstudents

这是一个修改后的版本:

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

typedef struct student_t {
    char *name;
    float gpa;
    int age;
} student_t;

int compmi(const void *a, const void *b) {
    const student_t * const *p1 = a;
    const student_t * const *p2 = b;
    return strcmp((*p1)->name, (*p2)->name);
}

int main(int argc, char **argv) {
    unsigned numrecords;
    int i = 0;
    char *lettergrade;

    // OPENS THE FILE IN BINARY
    FILE *input_file = fopen("input.bin", "rb");
    if (input_file == NULL) {
        fprintf(stderr, "cannot open input.bin\n");
        return 1;
    }
    // READS THE NUMBER OF RECORDS
    fread(&numrecords, sizeof(unsigned), 1, input_file);
    
    // allocate the array directly, no need for realloc
    student_t **students = malloc(sizeof(*students) * num_records);
    if (students == NULL) {
        fprintf(stderr, "allocation error\n");
        return 1;
    }

    // LOOPING THROUGH EACH ENTRY
    for (i = 0; i < numrecords; i++) {
        // ALLOCATE MEMORY
        if ((students[i] = malloc(sizeof(student_t))) == NULL
        ||  (students[i]->name = calloc(21, 1)) == NULL) {
            fprintf(stderr, "allocation error\n");
            return 1;
        }
        // READ NAME, GPA and AGE
        if (fread(students[i]->name, 20, 1, input_file) != 1
        ||  fread(&students[i]->gpa, sizeof(students[i]->gpa), 1, input_file) != 1
        ||  fread(&students[i]->age, sizeof(students[i]->age), 1, input_file) != 1) {
            fprintf(stderr, "error reading data for record %d / %d\n", i + 1, numrecords);
            return 1;
        }
    }
    fclose(input_file);

    //SORTING WITH QSORT
    qsort(students, numrecords, sizeof(*students), compmi);

    // PRINTING OUTPUT
    for (i = 0; i < numrecords; i++) {
        printf("%i of %d:\n", i + 1, numrecords);
        printf("Name: %s\n", students[i]->name);
        //printf("UPDATED GPA USE THIS: %.1f\n", students[i]->gpa);
        printf("GPA:  %.1f\n", students[i]->gpa);
        printf("Age:  %i\n", students[i]->age);
        printf("\n");
    }
    
    // FREEING MEMORY
    for (i = 0; i < numrecords; i++) {
        free(students[i]->name);
        free(students[i]);
    }
    free(students);
    
    return 0;
}

但请注意,对数据使用二进制格式是有问题的:

  • 各种类型的大小和表示形式可能会因系统而异。
  • 二进制文件需要精确的规范,并且不容易调试。
  • 文本文件是交换的首选格式。它们易于阅读和书写。

评论

0赞 CiaPan 3/9/2021
您没有完成分配测试:在分配给“students[i]->name”之前,您测试了是否,但未测试是否为 non-null。students[i]->name != NULLstudents[i]
0赞 chqrlie 3/9/2021
@CiaPan:好点子,答案修正了。鉴于该字段似乎具有固定长度,因此应将其定义为数组,而不是指向分配的内存,但 OP 没有提供结构定义,并且可能无法自由更改它。namechar name[21]char *