簡體   English   中英

在 C 中有一個指向多個不同大小的 LUT 的數組

[英]Having an array that points to multiple LUT with different sizes in C

我正在做一個程序,該程序使用兩個堆棧對學校項目進行排序,我想通過蠻力方法處理堆棧大小低於或等於 5 的情況,為此我有不同的包含查找表的結構,其中包含表示數字順序的 int 數組數組(對於每種可能的順序),以及包含對它們進行排序的相應操作序列的函數指針數組數組,這些結構中的每一個都對應於一個特定的數組大小(2、3、4、5)。 為了避免一個巨大的if森林,我想使用帶有指向不同數據的指針的公共結構( t_combi )的 while 循環訪問它們,但顯然它不起作用,我不知何故丟失了我的全局地址數組,因為當我比較訂單時,我在第一次迭代時遇到了段錯誤(嘗試使用 valgrind 訪問未分配的數據)。

代碼:

//  brute_force.h

#ifndef BRUTE_FORCE_H
# define BRUTE_FORCE_H

# include "resolver.h"

# define CNT_2 2
# define CNT_3 6
# define CNT_4 24
# define CNT_5 120

typedef struct s_mlx    *t_mlxptr;
typedef const char      *(*t_op)(t_stack *, t_stack *);

typedef struct  s_combi {
    int     cnt;
    int     **order;
    t_op    **op;
}   t_combi;

static const struct {
    int     cnt;
    int     order[CNT_2][2];
    t_op    op[CNT_2][2];
}   g_2combi = {
        .cnt = CNT_2,
        .order = {
            {0, 1},
            {1, 0}
        },
        .op = {
            {NULL},
            {sa, NULL}
        }
};

static const struct {
    int     cnt;
    int     order[CNT_3][3];
    t_op    op[CNT_3][3];
}   g_3combi = {
        .cnt = CNT_3,
        .order = {
            {0, 1, 2},
            {0, 2, 1},
            {1, 0, 2},
            ...
        },
        .op = {
            {NULL},
            {rra, sa, NULL},
            {sa, NULL},
            ...
        }
};

static const struct {
    int     cnt;
    int     order[CNT_4][4];
    t_op    op[CNT_4][7];
}   g_4combi = {
    .cnt = CNT_4,
    .order = {
        {0, 1, 2, 3},
        {0, 1, 3, 2},
        {0, 2, 1, 3},
        ...
    },
    .op = {
        {NULL},
        {pb, rra, sa, pa, NULL},
        {ra, sa, rra, NULL},
        ...
    }
};

static const struct {
    int     cnt;
    int     order[120][5];
    t_op    op[120][10];
}   g_5combi = {
    .cnt = CNT_5,
    .order = {
        {0, 1, 2, 3, 4},
        {0, 1, 2, 4, 3},
        {0, 1, 3, 2, 4},
        ...
    },
    .op = {
        {NULL},
        {rra, rra, sa, ra, ra, NULL},
        {pb, pb, sa, pa, pa, NULL},
        {pb, pb, rra, pa, pa, NULL},
        ...
    }
};

int brute_force(t_mlxptr mlx, t_stack *st[2], t_queue *instr);

#endif

// brute_force.c

#include <brute_force.h>
#include <resolver.h>

bool    same_order(const int *a, const int *b, size_t size)
{
    size_t  i = 0;

    while (++i < size)
    {
        if ((a[i - 1] < a[i] && b[i - 1] > b[i])
        || (a[i - 1] > a[i] && b[i - 1] < b[i]))
            return (false);
    }
    return (true);
}

void    apply_instructions(t_mlxptr mlx, t_stack *st[2], t_op *op, t_queue *instr)
{
    while (*op)
    {
        add_op(mlx, *op, st, instr); // function from resolver.h
        ++op;
    }
}

void    init_combi(t_combi combi[4])
{
    combi[0] = (t_combi) {
        .cnt = g_2combi.cnt,
        .order = (int**)g_2combi.order,
        .op = (t_op **)g_2combi.op
    };
    combi[1] = (t_combi) {
        .cnt = g_3combi.cnt,
        .order = (int**)g_3combi.order,
        .op = (t_op **)g_3combi.op
    };
    combi[2] = (t_combi) {
        .cnt = g_4combi.cnt,
        .order = (int**)g_4combi.order,
        .op = (t_op **)g_4combi.op
    };
    combi[3] = (t_combi) {
        .cnt = g_5combi.cnt,
        .order = (int**)g_5combi.order,
        .op = (t_op **)g_5combi.op
    };
}


int brute_force(t_mlxptr mlx, t_stack *st[2], t_queue *instr)
{
    const int *const    a_raw = stkcbegin(st[ST_A]); // pointer to a int array
    const size_t        size = stksize(st[ST_A]); // nbcount
    int                 i;

    t_combi             combi[4];
    
    init_combi(combi);
    if (stksorted(st[ST_A]))
        return (0);
    if (size > 5)
        return (1);
    i = -1;
    while (++i < combi[size - 2].cnt)
    {
        if (same_order(combi[size - 2].order[i], a_raw, size))
            apply_instructions(mlx, st, combi[size - 2].op[i], instr);
    }
    return (0);
}

主要問題是您將指向某種類型數組的指針轉換為指向某種類型指針的指針。 例如,在這段代碼中:

void    init_combi(t_combi combi[4])
{
    combi[0] = (t_combi) {
        .cnt = g_2combi.cnt,
        .order = (int**)g_2combi.order,
        .op = (t_op **)g_2combi.op
    };
    /* ... */
}

g_2combi.orderint的二維數組: int [CNT_2][2] 在初始化程序中,該值被轉換為指向其第一個元素的指針。 類型的元素的是int [2]陣列長度的2 int ),所以指針的元素的類型是int (*)[2]指向的數組長度2 int )。 但是,類型轉換操作將其轉換為指向不兼容類型int **指針(指向指向int指針的指針)。 combi[0].order[0]應該是int *類型,這與底層對象的類型不兼容: int [2]

類似地, g_2combi.op是的2維陣列t_opt_op [CNT_2][2] 在初始化,該值被轉換為指針類型的第一個元素t_op [2]陣列長度的2 t_op ),所以指針類型的t_op (*)[2]指向的數組長度2 t_op )。 類型轉換操作在指針轉換為t_op ** (指向指針t_op )。 combi[0].op[0]應該是t_op *類型,它與底層對象的類型不兼容: t_op [2]

解決該問題的一種方法是將所有變量g_2combig_3combi等定義為同一類型t_combi 保持一切不變,復合文字可用於初始化g_2combi.order等中的指針。例如:

typedef struct  s_combi {
    int     cnt;
    const int * const *order;
    const t_op * const *op;
} t_combi;

static const t_combi g_2combi = {
    .cnt = CNT_2,
    .order = (const int * const []){
        (const int []){0, 1},
        (const int []){1, 0}
    },
    .op = (const t_op * const []){
        (const t_op []){NULL},
        (const t_op []){sa, NULL}
    }
};

/* define g_3combi etc. in a similar way to the above. */

void    init_combi(t_combi combi[4])
{
    combi[0] = g_2combi;
    combi[1] = g_3combi;
    combi[2] = g_4combi;
    combi[3] = g_5combi;
}

(由於上面添加了const ness, apply_instruction函數的op參數需要從t_op *op更改為const t_op *op 。)

一個大問題是您將指針隱藏在 typedef 后面。 這只有一個目的:混淆程序員和其他閱讀代碼的人。

例如t_op **op; 沒有 typedef 的擴展創建一個類型的函數指針

typedef const char      *(***t_op)(t_stack *, t_stack *);

正如你所希望的那樣,這簡直是瘋了。 在你做任何其他事情之前,你需要擺脫這些類型定義和不必要的多重間接層。

函數指針的合理typedef可能如下所示(它實際上是函數的 typedef):

typedef char* t_op (t_stack*, t_stack*);

然后您將其用作t_op* op

總體而言,你的程序復雜的東西,聽起來像一個相當簡單的任務。 作為另一個例子,任何地方都不應該有任何強制轉換——所有這些都是為了隱藏錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM