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

问题描述

我有一个保存字符名称的数组结构。我想使用 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,input_file); // READ GPA
        fread(&students[i]->age,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;
}

解决方法

变量 a 指向一个 const 限定类型,但 p1 不指向一个 const 类型(但是那个指向的是什么是)。您需要在 const 之间添加 *

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);
}
,

代码中存在多个问题:

  • 比较函数将指向常量对象的指针转换为指向非常量对象本身的指针,以及指向常量student对象的指针。不保留原始常量。定义应该是:

    const student_t * const *p1 = a;
    const student_t * const *p2 = b;
    
  • 阅读循环应该在 i == numrecords 时停止,因此您应该使用 i < numrecords 而不是 i <= numrecords

  • fread 大小不正确:您应该指定成员类型的大小,而不是 student_t 结构的大小。

  • 您将 *students 传递给 qsort 而不是数组指针 students

这是修改后的版本:

#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,input_file) != 1
        ||  fread(&students[i]->gpa,sizeof(students[i]->gpa),input_file) != 1
        ||  fread(&students[i]->age,sizeof(students[i]->age),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",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;
}

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

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