投射 void* 指针

Casting a void* pointer

提问人:Trammy 提问时间:10/2/2023 最后编辑:Trammy 更新时间:10/19/2023 访问量:172

问:

当我尝试在 C lang 上的通用排序库中使用 compelx 结构时,我的代码中有问题:(您可以找到完整的代码 https://github.com/Tramontz/ASD_2023)

我有一个二进制合并插入排序,它输入一个空指针(数组的第一个元素),并且可以处理 int 和 string 的数组(所有 Unity 测试通过)。

现在我正在尝试将它与以下数组一起使用:

struct record{
  int id;
  char* string_field_1;
  int integer_field_2;
  double float_field_3;
};

存储在另一个结构中

struct _StructArray{
  void**array;
  unsigned long el_num;
  unsigned long array_capacity;
};

带子程序

void struct_array_add(StructArray *struct_array, void* element){
  if(struct_array->el_num >= struct_array->array_capacity){
    printf("array too short, must be reallocate \n");
    struct_array->array = (void**)realloc(struct_array->array,2*(struct_array->array_capacity)*sizeof(void*));
    struct_array->array_capacity = 2*struct_array->array_capacity;
  }
  struct_array->array[struct_array->el_num] = element;
  struct_array->el_num++;
}

void* struct_array_get(StructArray *struct_array, unsigned long index){
  return &(struct_array->array)[index];
}

我必须对 void**record 数组进行排序。

这是从 CSV 文件中获取的数据的示例

<位置:0,ID:0,字符串:noto,整数:233460,浮点数:32209.073312 >

<位置:1,ID:1,字符串:piangea,整数:4741192,浮点数:81176.622633 >

<位置:2,ID:2,字符串:spenti!,整数:1014671,浮点数:4476.013614 >

<位置:3, ID:3, 字符串:misericordia, 整数:496325, float:61628.929334 >

订购模式由

switch (field) {
      case 1://struct_array_get(array,0) return the first element of the array
          merge_binary_insertion_sort(struct_array_get(array,0), struct_array_size(array), sizeof(struct record), k, precedes_record_string_field);

所以基本上我用循环将我的所有数据存储在structArray中的记录*array中。

数组已正确加载,因为 print 函数

for(unsigned long i=0;i<el_num;i++){
    array_element = (struct record *)struct_array_get(array, i);
    printf("<POSIZION:%d, ID:%d, String:%s, Integer:%d, Float:%lf >\n",i,array_element->id,array_element->string_field_1,array_element->integer_field_2,array_element->float_field_3); 
  }

可以显示数组中的所有记录。

所以当调用排序函数时出现问题:

    void bin_insertion_sort(void *arr, int n, size_t elementSize, CompareFunction compare) {
        int i, loc, j;
        void *selected = malloc(elementSize);
        if (selected == NULL) {
          fprintf(stderr, "Errore nell'allocazione di memoria per 'selected'\n");
           exit(EXIT_FAILURE);
         }
        for (i = 1; i < n; ++i) {
            j = i - 1;
            memcpy(selected, arr + i * elementSize, elementSize);

            // Find location where selected should be inserted
            loc = binary_search(arr, selected, 0, j, compare, elementSize);

我在 void *selected 中存储了我想在数组中查找位置的项目,并调用二进制搜索


int binary_search(void *arr, void *item, int low, int high, CompareFunction compare, size_t elementSize) {
        if (high <= low){
            return (compare(item, arr + low * elementSize) > 0) ? (low + 1) : low ;

我们只能专注于binary_search,这就是问题所在: 当我调用 return (compare(item, arr + low * elementSize) > 0) 时?(低 + 1) : 低 ;对于记录的数组,使用此比较函数

 static int precedes_record_string_field(const void* r1_p, const void* r2_p) {
    if (r1_p == NULL || r2_p == NULL) {
        fprintf(stderr, "precedes_record_string_field: one of the parameters is a null pointer\n");
        exit(EXIT_FAILURE);
    }

    const struct record* rec1_p = (const struct record*)r1_p;
    const struct record* rec2_p = (const struct record*)r2_p;

    printf("Record 1: ID=%d, String=%s, Integer=%d, Float=%f\n", rec1_p->id, rec1_p->string_field_1, rec1_p->integer_field_2, rec1_p->float_field_3);
    sleep(1);
    printf("Record 2: ID=%d, String=%s, Integer=%d, Float=%f\n", rec2_p->id, rec2_p->string_field_1, rec2_p->integer_field_2, rec2_p->float_field_3);
sleep(5);

    return strcmp(rec1_p->string_field_1, rec2_p->string_field_1);
}

它打印 rec2 数据,但不打印 rec1 数据,所以我认为它可以转换 arr + low * elementSize 指针,但不能转换我通过 compare(item, arr + low * elementSize) 传递的 void item* 指针并存储在 rec1(item) 和 rec2(arr + low * elementSize) 中。

我在内存地址管理中做错了什么? 也许我正在用 item 处理所有 structArray,而不是 record* 数组的第二个元素?

我被困住了,因为我所有使用单个、null 和多个字符串和整数数组的 Unity 测试都可以正常工作。

谢谢大家。

C 算法 排序 转换 void-pointer

评论

1赞 Refugnic Eternium 10/2/2023
这真的是您发布的最小可重复示例吗?
0赞 Refugnic Eternium 10/2/2023
另外,您是否尝试过使用调试器单步执行代码?看看哪里可能出错?
0赞 Peter - Reinstate Monica 10/2/2023
问题当然不在于强制转换,前提是确实存在结构类型的对象。错误可以是任何东西——内存管理、指针算术、拼写错误。
4赞 Lundin 10/2/2023
你不能对虚空指针进行算术运算,所以胡言乱语也是如此。arr + low * elementSize
1赞 Lundin 10/2/2023
@Peter-ReinstateMonica 我知道这一点,但问题中没有任何内容表明 OP 正在进行内核 goo 编程。在正常的 C 编程中,我们远离不良做法。在 Linux 内核编程中,我们接受不良做法并积极寻求使用它们......SO 的总体目标应该是教授良好的编程实践。

答:

1赞 arfneto 10/3/2023 #1

你写的方式看起来非常非常复杂。

Maybe you could test the functions first...

I will show you a methodical way of writing his,
using your `struct` and `qsort`,
that you can easily adapt...

编辑:在下面添加了第二部分,即第二部分。为此,我添加了代码,以使用下面的相同方法对 void** 数组进行排序,然后像原始问题中一样对 StructArray 进行排序,作为分离容器、方法和算法的方法的示例。这是对复制和粘贴的大量使用:更改仅在比较函数(每个函数 2 行)和添加到 StructArray 的函数(4 行)中,以提取指针数组的基址。

把东西分开

typedef struct
{
    int    id;
    char*  string;
    int    i_field;
    double d_field;
} Target;

int cmp_1(const void*, const void*);
int cmp_2(const void*, const void*);
int cmp_3(const void*, const void*);
int cmp_4(const void*, const void*);

int so_show(unsigned, Target[], const char*);

在这里,我们有您的数据记录、4 个必需函数和一个显示结果的函数

使用封装并围绕数据编写代码。

看这个:

    Target some_value[] = {
        [0] =
            {.id      = 42,
             .string  = "value 33",
             .i_field = 4242,
             .d_field = 42.42},
        [1] =
            {.id      = 4,
             .string  = "stack",
             .i_field = 42,
             .d_field = 42.242},
        [2] =
            {.id      = 342,
             .string  = "overflow",
             .i_field = 4,
             .d_field = 142.42},
        [3] =
            {.id      = 412,
             .string  = "take the survey",
             .i_field = 2,
             .d_field = 2142.42},
};

这是用于测试所有功能的数据。

###' main用于测试###

这里:

  • 数组按声明打印
  • 数组按每个条件排序并显示
    so_show(4, some_value, "\nBefore sort:\t");

    qsort(some_value, 4, sizeof(Target), cmp_1);
    so_show(4, some_value, "\nAfter sort by id:\t");

    qsort(some_value, 4, sizeof(Target), cmp_2);
    so_show(
        4, some_value, "\nAfter sort by string field:\t");

    qsort(some_value, 4, sizeof(Target), cmp_3);
    so_show(
        4, some_value, "\nAfter sort by integer field:\t");

    qsort(some_value, 4, sizeof(Target), cmp_4);
    so_show(
        4, some_value, "\nAfter sort by double field:\t");

输出


Before sort:    4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|   42 | "            value 33" |     4242 |      42.4200 |
|    4 | "               stack" |       42 |      42.2420 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|


After sort by id:       4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|


After sort by string field:     4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|  342 | "            overflow" |        4 |     142.4200 |
|    4 | "               stack" |       42 |      42.2420 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|   42 | "            value 33" |     4242 |      42.4200 |
|=========================================================|


After sort by integer field:    4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|  412 | "     take the survey" |        2 |    2142.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|=========================================================|


After sort by double field:     4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|

而且似乎还可以。

这样更容易:首先测试所有功能。

既然你说代码已经适用于整数,那么只要确保排序代码确实抽象了数据记录。 一般来说,只是编写正确的交换函数的情况。并特别注意导航过程......

完整代码C

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

typedef struct 
{
    int    id;
    char*  string;
    int    i_field;
    double d_field;
}  Target;

int cmp_1(const void*, const void*);
int cmp_2(const void*, const void*);
int cmp_3(const void*, const void*);
int cmp_4(const void*, const void*);

int so_show(unsigned, Target[], const char*);

int main(void)
{
    Target some_value[] = {
        [0] =
            {.id      = 42,
             .string  = "value 33",
             .i_field = 4242,
             .d_field = 42.42},
        [1] =
            {.id      = 4,
             .string  = "stack",
             .i_field = 42,
             .d_field = 42.242},
        [2] =
            {.id      = 342,
             .string  = "overflow",
             .i_field = 4,
             .d_field = 142.42},
        [3] =
            {.id      = 412,
             .string  = "take the survey",
             .i_field = 2,
             .d_field = 2142.42},
    };

    so_show(4, some_value, "\nBefore sort:\t");

    qsort(some_value, 4, sizeof(Target), cmp_1);
    so_show(4, some_value, "\nAfter sort by id:\t");

    qsort(some_value, 4, sizeof(Target), cmp_2);
    so_show(
        4, some_value, "\nAfter sort by string field:\t");

    qsort(some_value, 4, sizeof(Target), cmp_3);
    so_show(
        4, some_value, "\nAfter sort by integer field:\t");

    qsort(some_value, 4, sizeof(Target), cmp_4);
    so_show(
        4, some_value, "\nAfter sort by double field:\t");

};  // main

int cmp_1(void* one, void* other)
{
    Target* a = one;
    Target* b = other;
    if (a->id < b->id) return -1;
    if (a->id == b->id) return 0;
    return 1;
};

int cmp_2(void* one, void* other)
{   // now for the string
    Target* a = one;
    Target* b = other;
    return strcmp(a->string, b->string);
};

int cmp_3(void* one, void* other)
{
    Target* a = one;
    Target* b = other;
    if (a->i_field < b->i_field) return -1;
    if (a->i_field == b->i_field) return 0;
    return 1;
};

int cmp_4(void* one, void* other)
{
    Target* a = one;
    Target* b = other;
    if (a->d_field < b->d_field) return -1;
    if (a->d_field == b->d_field) return 0;
    return 1;
};
int so_show(unsigned N, Target r[], const char* msg)
{
    if (r == NULL) return -1;
    if (msg != NULL) printf("%s", msg);
    printf("%d records\n", N);
    const char* l0 =
        "\
|  id  |           string value |  integer |       double |";
    const char* l1 =
        "\
|=========================================================|";
    printf("%s\n%s\n%s\n", l1,l0,l1);
    for ( unsigned u=0;u<N;u+=1)
        printf(
            "| %4d | \"%20s\" | %8d | %12.4f |\n", r[u].id,
            r[u].string, r[u].i_field, r[u].d_field);
    printf("%s\n\n",l1);
    return 0;
}

第二部分

这是第二个示例:main.c

int main(void)
{
    Target some_value[] = {
        [0] =
            {.id      = 42,
             .string  = "value 33",
             .i_field = 4242,
             .d_field = 42.42},
        [1] =
            {.id      = 4,
             .string  = "stack",
             .i_field = 42,
             .d_field = 42.242},
        [2] =
            {.id      = 342,
             .string  = "overflow",
             .i_field = 4,
             .d_field = 142.42},
        [3] =
            {.id      = 412,
             .string  = "take the survey",
             .i_field = 2,
             .d_field = 2142.42},
    };

    const N = sizeof(some_value) / sizeof(some_value[0]);

    test_with_struct_array(
        N, some_value,
        "\n\n\t***** using an array of structs *****\n\n");
    test_with_voidp_array(
        N, some_value,
        "\n\n\t***** using a 'void**' *****\n\n");
    test_with_Struct_Array(
        N, some_value,
        "\n\n\t***** using an original 'StructArray' "
        "*****\n\n");

    return 0;
};  // main

test_with_struct_array()是原始程序。第二个函数对数组中的相同数组进行排序,以便单独测试机制,第三个函数使用作者的原始---,稍作修改,请参阅下面的代码。void**StructArray

usind avoid**

这是使用原始数据构建数组的代码:

    Target** base = malloc(n * sizeof(Target*));
    for (unsigned i = 0; i < n; i += 1)
        base[i] = &some_value[i];

比较功能都是不同的,因为访问实际数据的间接性达到了一个新的水平。新函数来自 这里是一对,比较了 from:cmp_[5678]cmp_[1234]i_fieldTarget


int cmp_3(const void* one, const void* other)
{
    Target* a = (Target*)one;
    Target* b = (Target*)other;
    if (a->i_field < b->i_field) return -1;
    if (a->i_field == b->i_field) return 0;
    return 1;
};

int cmp_7(const void* one, const void* other)
{
    Target* a = (Target*)*((const void**)one);
    Target* b = (Target*)*((const void**)other);
    if (a->i_field < b->i_field) return -1;
    if (a->i_field == b->i_field) return 0;
    return 1;
};

区别仅在于获取数据地址。由于也是一回事,因此也在那里使用这些功能。StructArrayvoid**

添加了姊妹函数以显示来自不同源的数据,因此输出完全相同,符合预期。

int so_show_one(Target*);
int so_show(
    unsigned, Target[], int (*show)(void*), const char*);
int so_show_from_StructArray(
    StructArray*, int (*show)(void*), const char*);
int so_show_from_voidp_array(
    unsigned, void**, int (*show)(void*), const char*);

第一个函数显示单个数据记录,因此可以用于所有 3 种格式。它作为参数传递,因此如果需要,可以很容易地为每个测试使用备用显示器。

的变化StructArray

void* struct_array_get_base(StructArray* x)
{
    if (x == NULL) return NULL;
    return &(x->array)[0];
}

添加此函数是为了从内部获取基址StructArray

用作容器时StructArray

int test_with_Struct_Array(
    unsigned n, Target some_value[], const char* msg)
{
    if (msg != NULL) printf("%s", msg);

    StructArray* tgt = struct_array_create();
    for (size_t i = 0; i < n; i += 1)
        struct_array_add(tgt, &some_value[i]);
    fprintf(
        stderr, "\n\t%u values inside target StructArray\n",
        struct_array_size(tgt));

    so_show_from_StructArray(
        tgt, so_show_one,
        "\n    With data inside StructArray:\t");

    // this is the base for sort
    void*  array_base = struct_array_get_base(tgt);
    size_t size       = struct_array_size(tgt);
    qsort(array_base, size, sizeof(void*), cmp_5);
    so_show_from_StructArray(
        tgt, so_show_one, "\n\tAfter sort by id:\t");

这就是在测试函数开始时对容器进行排序的方式。这应该适用于 的连续数组上的任何排序算法。void*

希望对您有所帮助

第二个示例的代码

#pragma pack(push, 1)
#pragma pack(show)

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

#include "struct_array.h"

typedef struct
{
    int    id;
    char*  string;
    int    i_field;
    double d_field;
} Target;

int cmp_1(const void*, const void*);
int cmp_2(const void*, const void*);
int cmp_3(const void*, const void*);
int cmp_4(const void*, const void*);

int cmp_5(const void*, const void*);
int cmp_6(const void*, const void*);
int cmp_7(const void*, const void*);
int cmp_8(const void*, const void*);

int so_show_one(Target*);
int so_show(
    unsigned, Target[], int (*show)(void*), const char*);
int so_show_from_StructArray(
    StructArray*, int (*show)(void*), const char*);
int so_show_from_voidp_array(
    unsigned, void**, int (*show)(void*), const char*);

int test_with_struct_array(unsigned, Target[], const char*);
int test_with_voidp_array(unsigned, Target[], const char*);
int test_with_Struct_Array(unsigned, Target[], const char*);

int main(void)
{
    Target some_value[] = {
        [0] =
            {.id      = 42,
             .string  = "value 33",
             .i_field = 4242,
             .d_field = 42.42},
        [1] =
            {.id      = 4,
             .string  = "stack",
             .i_field = 42,
             .d_field = 42.242},
        [2] =
            {.id      = 342,
             .string  = "overflow",
             .i_field = 4,
             .d_field = 142.42},
        [3] =
            {.id      = 412,
             .string  = "take the survey",
             .i_field = 2,
             .d_field = 2142.42},
    };

    const N = sizeof(some_value) / sizeof(some_value[0]);

    test_with_struct_array(
        N, some_value,
        "\n\n\t***** using an array of structs *****\n\n");
    test_with_voidp_array(
        N, some_value,
        "\n\n\t***** using a 'void**' *****\n\n");
    test_with_Struct_Array(
        N, some_value,
        "\n\n\t***** using an original 'StructArray' "
        "*****\n\n");

    return 0;
};  // main

int cmp_1(const void* one, const void* other)
{  // compare ids
    Target* a = (Target*)one;
    Target* b = (Target*)other;
    if (a->id < b->id) return -1;
    if (a->id == b->id) return 0;
    return 1;
};

int cmp_2(const void* one, const void* other)
{  // now for the string
    Target* a = (Target*)one;
    Target* b = (Target*)other;
    return strcmp(a->string, b->string);
};

int cmp_3(const void* one, const void* other)
{
    Target* a = (Target*)one;
    Target* b = (Target*)other;
    if (a->i_field < b->i_field) return -1;
    if (a->i_field == b->i_field) return 0;
    return 1;
};

int cmp_4(const void* one, const void* other)
{  // for doubles
    Target* a = (Target*)one;
    Target* b = (Target*)other;
    if (a->d_field < b->d_field) return -1;
    if (a->d_field == b->d_field) return 0;
    return 1;
};

int cmp_5(const void* one, const void* other)
{
    Target* a = (Target*)*((const void**)one);
    Target* b = (Target*)*((const void**)other);
    if (a->id < b->id) return -1;
    if (a->id == b->id) return 0;
    return 1;
};

int cmp_6(const void* one, const void* other)
{  // now for the string
    Target* a = (Target*)*((const void**)one);
    Target* b = (Target*)*((const void**)other);
    return strcmp(a->string, b->string);
};

int cmp_7(const void* one, const void* other)
{
    Target* a = (Target*)*((const void**)one);
    Target* b = (Target*)*((const void**)other);
    if (a->i_field < b->i_field) return -1;
    if (a->i_field == b->i_field) return 0;
    return 1;
};

int cmp_8(const void* one, const void* other)
{  // sort as double
    Target* a = *((void**)one);
    Target* b = *((void**)other);
    if (a->d_field < b->d_field) return -1;
    if (a->d_field == b->d_field) return 0;
    return 1;
};

int so_show(
    unsigned N, Target r[], int (*show)(void*),
    const char* msg)
{
    if (r == NULL) return -1;
    if (msg != NULL) printf("%s", msg);
    printf("%d records\n", N);
    const char* l0 =
        "\
|  id  |           string value |  integer |       double |";
    const char* l1 =
        "\
|=========================================================|";
    printf("%s\n%s\n%s\n", l1, l0, l1);
    for (unsigned u = 0; u < N; u += 1) show(r + u);
    printf("%s\n\n", l1);
    return 0;
}

int so_show_one(Target* one)
{
    printf(
        "| %4d | \"%20s\" | %8d | %12.4f |\n", one->id,
        one->string, one->i_field, one->d_field);
    return 0;
}

int so_show_from_StructArray(
    StructArray* A, int (*show)(void*), const char* msg)
{
    if (A == NULL) return -1;
    if (show == NULL) return -2;
    if (msg != NULL) printf("%s", msg);
    unsigned long N = struct_array_size(A);
    printf("%u records\n", N);
    const char* l0 =
        "\
|  id  |           string value |  integer |       double |";
    const char* l1 =
        "\
|=========================================================|";
    printf("%s\n%s\n%s\n", l1, l0, l1);
    for (unsigned u = 0; u < N; u += 1)
        show((Target*)struct_array_get(A, u));
    printf("%s\n\n", l1);
    return 0;
}

int so_show_from_voidp_array(
    unsigned N, void** base, int (*show)(void*),
    const char* msg)
{
    if (base == NULL) return -1;
    if (show == NULL) return -2;
    if (N <= 0) return -3;
    if (msg != NULL) printf("%s", msg);
    printf("%u records\n", N);
    const char* l0 =
        "\
|  id  |           string value |  integer |       double |";
    const char* l1 =
        "\
|=========================================================|";
    printf("%s\n%s\n%s\n", l1, l0, l1);
    for (unsigned u = 0; u < N; u += 1)
        show((Target*)base[u]);
    printf("%s\n\n", l1);
    return 0;
}

int test_with_struct_array(
    unsigned n, Target some_value[], const char* msg)
{
    if (msg != NULL) printf("%s", msg);

    so_show(
        n, some_value, so_show_one, "\n    Before sort:\t");

    qsort(some_value, n, sizeof(Target), cmp_1);
    so_show(
        n, some_value, so_show_one,
        "\n    After sort by id:\t");

    qsort(some_value, n, sizeof(Target), cmp_2);
    so_show(
        n, some_value, so_show_one,
        "\n    After sort by string field:\t");

    qsort(some_value, n, sizeof(Target), cmp_3);
    so_show(
        n, some_value, so_show_one,
        "\n    After sort by integer field:\t");

    qsort(some_value, n, sizeof(Target), cmp_4);
    so_show(
        n, some_value, so_show_one,
        "\n    After sort by double field:\t");

    return 0;
}

int test_with_voidp_array(
    unsigned n, Target some_value[], const char* msg)
{
    if (msg != NULL) printf("%s", msg);

    Target** base = malloc(n * sizeof(Target*));

    for (unsigned i = 0; i < n; i += 1)
        base[i] = &some_value[i];

    so_show_from_voidp_array(
        n, base, so_show_one, "\tbefore sort: ");

    size_t sz_one = sizeof(Target*);
    qsort(&base[0], n, sz_one, cmp_5);
    so_show_from_voidp_array(
        n, base, so_show_one, "\tsorted by id field: ");

    qsort(&base[0], n, sz_one, cmp_8);
    so_show_from_voidp_array(
        n, base, so_show_one, "\tsorted by double field: ");

    qsort(&base[0], n, sz_one, cmp_7);
    so_show_from_voidp_array(
        n, base, so_show_one,
        "\tsorted by integer field: ");

    qsort(&base[0], n, sz_one, cmp_6);
    so_show_from_voidp_array(
        n, base, so_show_one, "\tsorted by string field: ");
    return 0;
}

int test_with_Struct_Array(
    unsigned n, Target some_value[], const char* msg)
{
    if (msg != NULL) printf("%s", msg);

    StructArray* tgt = struct_array_create();
    for (size_t i = 0; i < n; i += 1)
        struct_array_add(tgt, &some_value[i]);
    fprintf(
        stderr, "\n\t%u values inside target StructArray\n",
        struct_array_size(tgt));

    so_show_from_StructArray(
        tgt, so_show_one,
        "\n    With data inside StructArray:\t");

    // this is the base for sort
    void*  array_base = struct_array_get_base(tgt);
    size_t size       = struct_array_size(tgt);
    qsort(array_base, size, sizeof(void*), cmp_5);
    so_show_from_StructArray(
        tgt, so_show_one, "\n\tAfter sort by id:\t");

    qsort(array_base, size, sizeof(void*), cmp_6);
    so_show_from_StructArray(
        tgt, so_show_one,
        "\n\tAfter sort by string field:\t");

    qsort(array_base, size, sizeof(void*), cmp_7);
    so_show_from_StructArray(
        tgt, so_show_one,
        "\n    After sort by integer field:\t");

    qsort(array_base, size, sizeof(void*), cmp_8);
    so_show_from_StructArray(
        tgt, so_show_one,
        "\n    After sort by double field:\t");

    return 0;
}

第 3 次测试的输出

这并不有趣,因为它是 3 次相同的数据,但由从相同的原始数据构建的不同容器生成。

        ***** using an original 'StructArray' *****


        4 values inside target StructArray

    With data inside StructArray:       4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|


        After sort by id:       4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|


        After sort by string field:     4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|  342 | "            overflow" |        4 |     142.4200 |
|    4 | "               stack" |       42 |      42.2420 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|   42 | "            value 33" |     4242 |      42.4200 |
|=========================================================|


    After sort by integer field:        4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|  412 | "     take the survey" |        2 |    2142.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|=========================================================|


    After sort by double field: 4 records
|=========================================================|
|  id  |           string value |  integer |       double |
|=========================================================|
|    4 | "               stack" |       42 |      42.2420 |
|   42 | "            value 33" |     4242 |      42.4200 |
|  342 | "            overflow" |        4 |     142.4200 |
|  412 | "     take the survey" |        2 |    2142.4200 |
|=========================================================|

评论

0赞 Trammy 10/3/2023
谢谢,但是在这次尝试之后,我认为问题在于我的比较函数如何从 void* 转换为结构变量。更改 sizeof 后的输出为: 记录 1:ID=6893352,字符串=(null),整数=-824954186,浮点数=0.000000 记录 2:ID=0,字符串=noto,整数=233460,浮点数=32209.073312 所以,记录 2 是正确的,这意味着来自 arr + low * elementSize 的强制转换工作正常,但我不明白将记录 1 指向哪里,即 void* 项 pinter 的强制转换, 以这种方式构建: void item= malloc(elementSize); memcpy(selected, arr+ i elementSize, elementSize);
0赞 arfneto 10/3/2023
你能发布代码的实际版本吗?也许在 github 上或作为问题的编辑?我编写 4 个函数的方式对你不起作用吗?你们有经过测试的交换功能吗?
0赞 Trammy 10/13/2023
我修改了有关我的问题的信息,并专注于不起作用的 2 个电话。我尝试了您的版本,但它有效,因为您从 C 调用了一个库,我必须开发自己的排序库,所以我认为问题在于我如何解决空指针
0赞 arfneto 10/13/2023
这个问题与排序无关。我展示的是一种(也许)更简单的方法来围绕数据和函数进行编码。精确排序功能无关紧要。您对二进制合并插入排序的定义是什么?你有参考资料吗?编辑您的答案并将其放在那里,以便我们查看。
0赞 Trammy 10/13/2023
github.com/Tramontz/ASD_2023