Skip to main content
Arduino

Return to Answer

Answer the updated question.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Edit: Fixing the answer to match the latest version of the question.

Your code works, but not quite as you expect it to work. You wrote:

complexTaskDefinition tasks [ ] [4] = ...;

Here you are defining a 2D array of objects, while your intention was to define a one-dimensional array (why do I feel like I am repeating myself?).

complexTaskDefinition tasks [ ] [4] = {
 {taskC1, true, -1, 1000 },
 {taskC2, true, 10, 2000 },
 {taskC3, false, 3, 3000 },
};

This definition, although syntactically correct, is awfully wacky. You are defining tasks as an array of 3 items. Each item is itself an array of 4 objects, where the first object of the array is explicitly initialized, and the three others are implicitly initialized to all-bits-zero. So basically your definition is equivalent to this explicit version:

complexTaskDefinition tasks [3] [4] = {
 {{taskC1, true, -1, 1000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}},
 {{taskC2, true, 10, 2000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}},
 {{taskC3, false, 3, 3000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}}
};

Then you wrote:

task = tasks [ i ];

Here, tasks[i] is a row of the 2D array, i.e. a 1D array of 4 objects, whereas task is a pointer to object. The assignment is legit because here, like in most contexts, the array "decays" to a pointer to its first element. The above line is equivalent to the explicit version:

task = &tasks[i][0];

Quite fortunately, this happens to point to one of the elements of the array that has been explicitly initialized!

As an illustration of the above, here is a modified version of showComplexTaskList() that loops over all the tasks in the array:

void showComplexTaskList () {
 Serial.println ( F ( "\nComplex Task List:" ) );
 Serial.print(F("number of tasks: "));
 Serial.println(sizeof tasks / sizeof(complexTaskDefinition));
 for (uint8_t i = 0; i < TASK_COUNT; i++) {
 for (uint8_t j = 0; j < 4; j++) {
 task = &tasks[i][j];
 Serial.print ( '[' );
 Serial.print ( i );
 Serial.print ( F ("]["));
 Serial.print ( j );
 Serial.print ( F ( "] REPEAT:" ));
 Serial.print ( ( task->repeat ) ? "YES" : "NO" );
 Serial.print ( F ( ", DELAY:" ) );
 Serial.print ( task->delay );
 Serial.print ( F ( ", ITERATIONS:" ) );
 Serial.print ( task->iterations );
 Serial.println ();
 }
 }
}

Its output is:

Complex Task List:
number of tasks: 12
[0][0] REPEAT:YES, DELAY:1000, ITERATIONS:-1
[0][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[0][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[0][3] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][0] REPEAT:YES, DELAY:2000, ITERATIONS:10
[1][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][3] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][0] REPEAT:NO, DELAY:3000, ITERATIONS:3
[2][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][3] REPEAT:NO, DELAY:0, ITERATIONS:0

So your program works almost by chance: an error in the way you define the array cancels an error in the way you use it. This kind of cancelled error method is very bad programming practice. You are wasting memory in unused complexTaskDefinition objects. More importantly, your code doesn't express your intent, which makes the program way harder to understand and to debug.

The fix is to declare a 1D array, as this has always been the intention:

complexTaskDefinition tasks [ ] = {
 {taskC1, true, -1, 1000 },
 {taskC2, true, 10, 2000 },
 {taskC3, false, 3, 3000 },
};

Now, you can check that this array does only have three tasks, as reported by sizeof tasks / sizeof(complexTaskDefinition). To use the array, you can use a pointer if you want:

task = &tasks[i];
// ...
Serial.print ( ( task->repeat ) ? "YES" : "NO" );

Or you can directly request a member of tasks[i], as in

void showComplexVersion () {
 Serial.println ( F ( "\nComplex Version:" ) );
 for (uint8_t i = 0; i < TASK_COUNT; i++) {
 tasks[i].task();
 }
}

Now I have a question for you. Since I already explained your 1D vs. 2D array mistake in the first iteration of my answer, why did you persist with this in your edited question? If you are going to blatantly ignore the answers you get, at least say so in the question. This could save time to those who might consider helping you.


Edit: Fixing the answer to match the latest version of the question.

Your code works, but not quite as you expect it to work. You wrote:

complexTaskDefinition tasks [ ] [4] = ...;

Here you are defining a 2D array of objects, while your intention was to define a one-dimensional array (why do I feel like I am repeating myself?).

complexTaskDefinition tasks [ ] [4] = {
 {taskC1, true, -1, 1000 },
 {taskC2, true, 10, 2000 },
 {taskC3, false, 3, 3000 },
};

This definition, although syntactically correct, is awfully wacky. You are defining tasks as an array of 3 items. Each item is itself an array of 4 objects, where the first object of the array is explicitly initialized, and the three others are implicitly initialized to all-bits-zero. So basically your definition is equivalent to this explicit version:

complexTaskDefinition tasks [3] [4] = {
 {{taskC1, true, -1, 1000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}},
 {{taskC2, true, 10, 2000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}},
 {{taskC3, false, 3, 3000 }, {nullptr, false, 0, 0},
 {nullptr, false, 0, 0}, {nullptr, false, 0, 0}}
};

Then you wrote:

task = tasks [ i ];

Here, tasks[i] is a row of the 2D array, i.e. a 1D array of 4 objects, whereas task is a pointer to object. The assignment is legit because here, like in most contexts, the array "decays" to a pointer to its first element. The above line is equivalent to the explicit version:

task = &tasks[i][0];

Quite fortunately, this happens to point to one of the elements of the array that has been explicitly initialized!

As an illustration of the above, here is a modified version of showComplexTaskList() that loops over all the tasks in the array:

void showComplexTaskList () {
 Serial.println ( F ( "\nComplex Task List:" ) );
 Serial.print(F("number of tasks: "));
 Serial.println(sizeof tasks / sizeof(complexTaskDefinition));
 for (uint8_t i = 0; i < TASK_COUNT; i++) {
 for (uint8_t j = 0; j < 4; j++) {
 task = &tasks[i][j];
 Serial.print ( '[' );
 Serial.print ( i );
 Serial.print ( F ("]["));
 Serial.print ( j );
 Serial.print ( F ( "] REPEAT:" ));
 Serial.print ( ( task->repeat ) ? "YES" : "NO" );
 Serial.print ( F ( ", DELAY:" ) );
 Serial.print ( task->delay );
 Serial.print ( F ( ", ITERATIONS:" ) );
 Serial.print ( task->iterations );
 Serial.println ();
 }
 }
}

Its output is:

Complex Task List:
number of tasks: 12
[0][0] REPEAT:YES, DELAY:1000, ITERATIONS:-1
[0][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[0][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[0][3] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][0] REPEAT:YES, DELAY:2000, ITERATIONS:10
[1][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[1][3] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][0] REPEAT:NO, DELAY:3000, ITERATIONS:3
[2][1] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][2] REPEAT:NO, DELAY:0, ITERATIONS:0
[2][3] REPEAT:NO, DELAY:0, ITERATIONS:0

So your program works almost by chance: an error in the way you define the array cancels an error in the way you use it. This kind of cancelled error method is very bad programming practice. You are wasting memory in unused complexTaskDefinition objects. More importantly, your code doesn't express your intent, which makes the program way harder to understand and to debug.

The fix is to declare a 1D array, as this has always been the intention:

complexTaskDefinition tasks [ ] = {
 {taskC1, true, -1, 1000 },
 {taskC2, true, 10, 2000 },
 {taskC3, false, 3, 3000 },
};

Now, you can check that this array does only have three tasks, as reported by sizeof tasks / sizeof(complexTaskDefinition). To use the array, you can use a pointer if you want:

task = &tasks[i];
// ...
Serial.print ( ( task->repeat ) ? "YES" : "NO" );

Or you can directly request a member of tasks[i], as in

void showComplexVersion () {
 Serial.println ( F ( "\nComplex Version:" ) );
 for (uint8_t i = 0; i < TASK_COUNT; i++) {
 tasks[i].task();
 }
}

Now I have a question for you. Since I already explained your 1D vs. 2D array mistake in the first iteration of my answer, why did you persist with this in your edited question? If you are going to blatantly ignore the answers you get, at least say so in the question. This could save time to those who might consider helping you.

+ parsing the error message.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Try replacing

taskDefinition _tasks [ ] [4] = {

by

taskDefinition _tasks [ ] = {

In short, you have defined _tasks as a 2D array of objects (an array of arrays of objects) while you intend to use it as a 1D array.


Note that the error message is quite explicit if you take the time to parse it:

request for member 'task' in '_tasks[((int)i)]',

You are requesting _tasks[i].task,

which is of non-class type

but _tasks[i] is not an object.

type 'taskDefinition [4]'

It is instead an array of four taskDefinition objects.

Try replacing

taskDefinition _tasks [ ] [4] = {

by

taskDefinition _tasks [ ] = {

In short, you have defined _tasks as a 2D array of objects (an array of arrays of objects) while you intend to use it as a 1D array.

Try replacing

taskDefinition _tasks [ ] [4] = {

by

taskDefinition _tasks [ ] = {

In short, you have defined _tasks as a 2D array of objects (an array of arrays of objects) while you intend to use it as a 1D array.


Note that the error message is quite explicit if you take the time to parse it:

request for member 'task' in '_tasks[((int)i)]',

You are requesting _tasks[i].task,

which is of non-class type

but _tasks[i] is not an object.

type 'taskDefinition [4]'

It is instead an array of four taskDefinition objects.

Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Try replacing

taskDefinition _tasks [ ] [4] = {

by

taskDefinition _tasks [ ] = {

In short, you have defined _tasks as a 2D array of objects (an array of arrays of objects) while you intend to use it as a 1D array.

AltStyle によって変換されたページ (->オリジナル) /