Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data controlled programs in c++

Not to sure how to name this question because the problem itself is looking for a construct of which I don´t know its name.

The problem is I am dealing with programs whose control flow depends greatly of data.

For example I created a MIPS simulator which implemented a list of more than 50 instructions, each implemented on its own and everything governed by a huge switch case

switch (function){ //Function is an int, each function (eg SLL) is 
        case 0:    //associated with one
            if (state->debug_level > 0){
                fprintf(state->debug_out, "SLL\n");
            }
            step_err = SLL(state, rs, rt, rd, sa);
            break;
        case 2:
            if (state->debug_level > 0){
                fprintf(state->debug_out, "SRL\n");
            }
            step_err = SRL(state, rs, rt, rd, sa);
            break;
        case 3:
            if (state->debug_level > 0){
                fprintf(state->debug_out, "SRA\n");
            }
//

I have been told that this could have been implemented using function pointers, but to do so what I am looking for is a way of relating data of any kind, say a string to other data, say an integer. I am aware of maps but wouldn't want to push back each pair. I am looking for some sort of array like syntax I think if seen before which might look something similar to this:

¿type? function_codes[]{
     0, "SLL";
     2, "SRL";
     3, "SRA";
     ...
 }

I am not looking for a solution to this problem but a generic approach to introducing quick relationships between data and using this to modify control flow.

EDIT AFTER ANSWERS What I was actually looking for but I didnt know was indeed maps but in particular its initialization syntax similar to an array (see accepted answer). This used with function pointers did the required job.

like image 263
gorilon Avatar asked Jan 20 '16 19:01

gorilon


People also ask

What are the 3 types of control structures in C?

There are three basic types of logic, or flow of control, known as: Sequence logic, or sequential flow. Selection logic, or conditional flow. Iteration logic, or repetitive flow.

What is the control of a program in C?

In simple words, Control statements in C help the computer execute a certain logical statement and decide whether to enable the control of the flow through a certain set of statements or not. Also, it is used to direct the execution of statements under certain conditions.

What are the 5 data types in C?

Types of Data Types in CFloating-point, integer, double, character. Union, structure, array, etc.


2 Answers

As you guessed, function pointers are in fact a good way to do this. Since you specify that you don't want to use a Map, this is how you would implement your integer-based function dispatch using an array of function pointers. Note that since I don't know the type signature of your MIPS functions (SLL, SRL, etc.) I've used dummy placeholder type names.

typedef ret_t (*mips_func)(arg1_t, arg2_t, arg3_t, arg4_t, arg5_t);

mips_func function_codes[] = {
    &SLL,
    &SRL,
    &SRA,
    ...
};

//...Later, in the part of your code that used to contain the big switch statement
step_err = (*function_codes[function])(state, rs, rt, rd, sa);

The syntax &SLL gets a pointer to the function SLL, which I assume is already in scope because you can call it directly from your switch statement.

Note that this assumes the numeric codes for the functions are a continuous sequence of integers from 0 to [max code value]. If some numeric codes are unused, then you will either need to leave explicit gaps in your array (by placing a NULL pointer in one or more entries) or use std::map<int, mips_func> so that you can use arbitrary non-continuous integer values as keys to functions. Fortunately, using a Map still doesn't require push_backing each element, since C++ now has initializer lists. The same code using a Map would look like this:

typedef ret_t (*mips_func)(arg1_t, arg2_t, arg3_t, arg4_t, arg5_t);

std::map<int, mips_func> function_codes = {
    {0, &SLL},
    {2, &SRL},
    {4, &SRA},
    ...
};

//Using the Map looks exactly the same, due to its overloaded operator[]
step_err = (*function_codes[function])(state, rs, rt, rd, sa);
like image 197
Edward Avatar answered Oct 15 '22 06:10

Edward


For simplify you can use associative containers. If the order is important then use std::map, or std::unordered_map in the other case.

And you can use syntax similar to the desired

std::map<size_t, std::string> codes_map = decltype(codes_map) {
    { 0, "val1" },
    { 1, "val2" }
};
like image 27
malchemist Avatar answered Oct 15 '22 06:10

malchemist