2
int led_p1[8] = {0x01, 0x02, 0x04, 0x08, 
                 0x10, 0x20, 0x40, 0x80};
int led_p2[8] = {0x81, 0x42, 0x24, 0x18,
                 0x18, 0x24, 0x42, 0x81};
int led_p3[8] = {0xFF, 0x00, 0xFF, 0x00,
                 0xFF, 0x00, 0xFF, 0x00};

int led_pattern[8] = {};
int pattern_idx = 0;



// select pattern for now
switch(pattern_idx)
{
    case 0: 
        led_pattern = led_p1;
        pattern_idx++;
        break;
    case 1: 
        led_pattern = led_p2;
        pattern_idx++;
        break;
    case 2: 
        led_pattern = led_p3;
        pattern_idx = 0;
        break;
}

I tried doing the above, I am going to loop round idx, copying a new sequence into the led_pattern, then loop round that, come back, get the next one.

I found a method to pass a whole array using a vector here; C++: copy array

But vectors (I believe) don't work on the compiler I am using (avr-gcc/c++)

How can I implement this within C++? I know in python the below would work, I can assign an array to another variable, and it "clones" it.

Thanks

Community
  • 1
  • 1
jjjjj
  • 73
  • 1
  • 1
  • 5
  • I don't understand; why can't you do `led_pattern[0] = led_p1[0]` .. etc? –  Jul 17 '12 at 20:53

6 Answers6

4

Do you really need to copy into led_pattern? Are you going to change the contents? If it's essentially const, why don't you declare led_pattern as a pointer to an int? That would be much more efficient as you'll just be pointing to one of the three existing arrays rather than copying them.

If not, use memcpy to copy from one of your three arrays into led_pattern

Component 10
  • 10,247
  • 7
  • 47
  • 64
  • I think I may try this along with the others, as to be honest, yes I do just want to use and not modify the values.Thanks – jjjjj Jul 17 '12 at 21:09
  • +1 for identifying X, not solving Y, in [the XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Robᵩ Jul 17 '12 at 21:14
  • Great read on the XY problem, never heard of it. You learn something new every day! (well may two things in my case!) Thanks everyone. – jjjjj Jul 17 '12 at 21:21
3

Replace this line that doesn't do what you want:

led_pattern = led_p1;

With any one of these that will, in descending order of preference.

std::copy(led_p1, led_p1 + 8, led_pattern);

memcpy(led_pattern, led_p1, sizeof led_p1);

for(int i = 0; i < 8; i++) led_pattern[i] = led_p1[i];
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • Or better yet, use [Boost.Array](http://www.boost.org/libs/array/) which has proper copy semantics out of the box. – ildjarn Jul 17 '12 at 20:55
  • 2
    Or better, better yet, use `std::array` if your compiler supports it. – Robᵩ Jul 17 '12 at 20:55
  • Although, if "vectors don't work on the compiler I am using," it is kind of hard to know what will. – Robᵩ Jul 17 '12 at 20:57
  • It's possible that vectors don't work because exceptions are disabled; if so, `array<>` should still be fine. – ildjarn Jul 17 '12 at 20:58
  • @Robᵩ vectors may not be supported because the platform does not have a heap implementation, and hence no dynamic memory allocation. But `std::array` should work if that's the limitation. – Praetorian Jul 17 '12 at 20:58
  • Your `memcpy` will not work. sizeof led_p1 will give you the size of a pointer instead of an array. – SwiftMango Jul 17 '12 at 21:01
  • @texasbruce No it won't, it'll return `8 * sizeof(int)` – Praetorian Jul 17 '12 at 21:02
  • @Rob I made a mistake then. sizeof is quite different in C++ than in C – SwiftMango Jul 17 '12 at 21:07
  • I believe it does have a heap, and that certain elements like vectors and inheritance, work very poorly on 8 bit MCU's. I will have a go at copy first, then memcpy (I know this should work as C is rock solid on the AVR) I was hoping to avoid a loop, and sorry guys I do not think I can use anything out of the standard library, ideally I shouldn't have to anyway! Thanks everyone for all the information to work on. – jjjjj Jul 17 '12 at 21:07
  • @user1337077 - Seriously consider the advice to make `led_pattern` a `const int*` pointer that variously points at `led_p1`, `led_p2` and `led_p3`. That is certainly better advice, assuming it is possible in your application. – Robᵩ Jul 17 '12 at 21:09
  • @texasbruce: sizeof is not different in C++ and C. – Jesse Good Jul 17 '12 at 21:10
  • 1
    @texasbruce - S'okay, mistakes happen. I hope I didn't sound too harsh. You should know, however, that you'll get [the same answer in C](http://ideone.com/DLRgD). – Robᵩ Jul 17 '12 at 21:12
  • Yes, I have tried the pointer and it works. This is exactly what I wanted to accomplish. Thanks. – jjjjj Jul 17 '12 at 21:19
  • @Rob Although it smells like sarcasm, I still take it. I thought `sizeof(array)` is the same as `sizeof(pointer)` because they are basically the same thing, but it turns out I am wrong. On my 64bit computer, `sizeof(10 chars array) is 10`, and `sizeof(pointer to this char array) is 8 (8 is for 8 bytes = 64bits)`. – SwiftMango Jul 18 '12 at 02:14
3

If I'm reading the OP correctly, you do not want a deep copy, but want to switch what array is being used for the LEDs. So you would make a pointer that you can switch among arrays, like so:

int led_p1[8] = {0x01, 0x02, 0x04, 0x08, 
                 0x10, 0x20, 0x40, 0x80};
int led_p2[8] = {0x81, 0x42, 0x24, 0x18,
                 0x18, 0x24, 0x42, 0x81};
int led_p3[8] = {0xFF, 0x00, 0xFF, 0x00,
                 0xFF, 0x00, 0xFF, 0x00};

int *led_pattern = led_p1; //Starting point
int pattern_idx = 0;

// select pattern for now
switch(pattern_idx)
{
    case 0: 
        led_pattern = led_p1;
        pattern_idx++;
        break;
    case 1: 
        led_pattern = led_p2;
        pattern_idx++;
        break;
    case 2: 
        led_pattern = led_p3;
        pattern_idx = 0;
        break;
}

So now you can switch led_pattern to point at whichever led_p* array you're currently using.

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
JoeFish
  • 3,009
  • 1
  • 18
  • 23
2

A usual approach would be to use std::copy(). std::copy takes two iterators that denote the start and the end of the sequence to copy and a third parameter, as the destination:

std::copy( &led_p1[ 0 ], &led_p1[ sizeof(led_p1) / sizeof(led_p1[ 0 ]) ], &led_pattern[ 0 ])

Where the expression sizeof(led_p1) / sizeof(led_p1[ 0 ]) evaluates to 8, the number of elements in your array. Instead of using 3 distinct array with you LED pattern, you could use an array with 3 arrays and iterate over this 3 arrays.

Torsten Robitzki
  • 3,041
  • 1
  • 21
  • 35
  • 2
    FYI: if you have C++11 available, the first two args can be `std::begin(led_p1), std::end(led_p1)`. – Robᵩ Jul 17 '12 at 21:07
  • @Robᵩ end even, if you do not have C++11 available, thous functions are so handy, that I've putt them in every tool box on every project I've worked on ;-) It's just a one liner each. – Torsten Robitzki Jul 18 '12 at 06:22
1

To make a deep copy, you have to copy every single value in the first array to the new array. Instead of just assigning the old pointer to the new one, do a for loop on the number of elements in the array and assign each one to the new copy.

matzahboy
  • 3,004
  • 20
  • 25
1

To make a hard copy in the memory level, you might want to use the old C function: memcpy

memcpy (led_pattern,led_p1, 8 * sizeof(int));

8 should be replaced by array size if it is different.

Function explanation: www.cplusplus.com/reference/clibrary/cstring/memcpy/

#include <string.h> should also be used.(Edited as Prætorian said)

SwiftMango
  • 15,092
  • 13
  • 71
  • 136
  • 2
    If you `#include ` you should qualify function call as `std::memcpy`. To call it as `memcpy`, include `` instead. Or best of all, since the question is tagged C++, use `std::copy`. – Praetorian Jul 17 '12 at 21:05