user2864293
user2864293

Reputation: 392

C++ arrays and stuff

I must prefix, this is probably a softball question for someone who knows their stuff, but alas that does not describe me.

I am trying to write a function that takes a list of booleans, of some unknown length, and modifies each entry according to a few rules

Rule 1) If array[j] = false, then leave array[j] unchanged

Rule 2) if array[j] = true, then leave it true and turn any subsequent "trues" to "false"

My strategy is to make a function which will loop over the array, and once it finds the first true (if any) it will set the rest of the entries to false and break out of the loop. I will pass the function the size of the array and the first entry (from which I will obtain the address of the beginning of the array by de-referencing it).

The only assumptions I have to make (I think) are that 1) The array contents will be contiguous in memory 2) The memory won't be repurposed in between the creation of the array, and the calling of the function.

My function looks like this -

void takeFirstTrue(char size, bool list0)
{
bool* myPtr = NULL; 

for (char j = 0; j <= (size - 1); j++)
{
    myPtr = &list0 + j;

    if ( *myPtr )
    {
        for (char k = 0; k <= (size - 1); k++) { *(&list0 + k) = false;}
        *(&list0 + j) = true;
        j = size; 
    }
}
}

The odd thing here is that sometimes it works, and sometimes it mistakenly sets the first entry to true, regardless of the "real" value. I come from a lower level H/W background, so I'm used to thinking about register addresses and program counters and stuff like that. A lot of these higher level language features are new to me, so I'm assuming I'm violating some rule I'm unaware of.

PS - I'm sure there are nice libraries for handling this stuff. I've heard (though don't know much about) things like boost and smart pointers. Please don't recommend those, at least not just yet. I want to learn how to pull all the right levers myself.

Upvotes: 0

Views: 69

Answers (2)

Alwin Leerling
Alwin Leerling

Reputation: 191

You mention your hardware background. From this I suspect that your confusion comes from the difference between assembly and C subroutine calling conventions.

In assembly you use registers to pass parameters to functions. Here is does not matter whether you are at the call site or in the calling function, a register hold its value regardless where you are.

In higher level languages this does not hold true. Parameters are typically passed by value. This means that inside the function you only have a copy of the variable, not the variable itself. In order to get access to the actual variable you need to pass a pointer as a parameter (of which a copy is created) which you then dereference to get the variable at the call sites memory location.

I suggest to write some simple programs and use gcc with the -E switch to create assembly listings. You'll get some insight what the compiler does and present you with something you are probably more familiar with.

Good Luck

Upvotes: 1

M.M
M.M

Reputation: 141648

bool list0 is a single boolean. It is not a list. When you write &list0 + j you cause undefined behaviour.

Do this instead:

void takeFirstTrue(int size, bool list[])
{
    for (int j = 0; j < size; ++j)
    {
        bool *myPtr = &list[j];
        // ..
        list[k] = false;

I used int instead of char as you are less likely to overflow an int than a char. It's actually better to use size_t, as long as you are familiar with how unsigned types work in C++.

Upvotes: 2

Related Questions