Skip to main content
Arduino

Return to Answer

+ clarification array vs. many vars, and computed variable names.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

Edit: As a clarification, and per Delta_G's suggestion, I'll try to explain the difference between an array and a collection of variables. Each variable you define is mapped by the compiler (technically, the linker) to a memory area. You can think of the variable names as convenient names assigned to those memory locations. If you write:

Bounce rmd0(48, 10), rmd1(47, 10), rmd2(46, 10), ...;

You get:

 ┌───────┐ ┌───────┐ ┌───────┐
rmd0: | | rmd1: | | rmd2: | | ...
 └───────┘ └───────┘ └───────┘

In the picture above, the boxes are the memory areas. They are large enough to hold a Bounce object, i.e. their size is sizeof(Bounce). Each one has a name. You have no control over where, within the memory, those variables are allocated: it's the linker's call.

In contrast, when you declare an array, you get a single variable which is mapped to a contiguous memory area large enough to hold the whole array:

Bounce rmd[6] = { ... };

Gives:

 ┌───────┬───────┬───────┬───────┬───────┬───────┐
rmd: | | | | | | |
 └───────┴───────┴───────┴───────┴───────┴───────┘

The individual cells do not have a name, and you instead use indices to access them. For instance, rmd[0] references the first cell. Please, note that in this example there is no variable named rmd0: if you try to use that identifier the compiler will complain it is not defined. Again, an array is not a "collection of variables": it is a single variable.

The array cells do behave in some sense much like individual variables (they are called lvalues), as you can use rmd[0] in the same way you would have used rmd0 in the previous code. The point of using an array is that the indices do not need to be literals: you can use a variable instead (rmd[i], where i is a variable), which comes handy when you want to loop over all the cells.

Edgar pointed out that I can write the variable rmd3 by int i = 3 and rmd[i].

I hope it is now clear that this is not the case. There is no variable named rmd3 unless you create it explicitly. Declaring an array named rmddoes not create such a variable.

[Can I] "form" a variable by "characters"?

Your question is not very clear, but my guess is you are talking about computed variable names. This is a programming technique where you access a variable by computing its name at run time. For example, you combine the strings "rmd" and "3" in order to build the name of the variable "rmd3". Then you use this computed name to access the variable that has this name.

Computed variable names are quite often supported by interpreted languages. For example, in PHP this is called variable variables:

$foobar = 42; // the variable we want to access
$start = "foo"; // one piece of the name
$end = "bar"; // the other piece
$name = $start . $end; // build the name from its pieces
print $name . "\n"; // prints the variable name: "foobar"
print $$name . "\n"; // prints the variable's value: "42"

Computed variable names are not supported by C++, which is the language you use to program an Arduino. And for a good reason: when the compiler translates your program to machine code, the names of the variables are lost, they do not make their way to the actual Arduino. And this is a good thing, as you would not want those names to consume memory on the microcontroller.

Note that the names are present in the .elf file, as they could be useful for debugging. If you were programming for a PC, you program could in principle look into the file and find those names. On Linux you would do that with the dlopen() and dlsym() functions, from the libdl library. The libdl technique is, however, very far from the capabilities of your typical Arduino, orders of magnitude more complex than a simple array, and perfectly useless for your use case.


Edit: As a clarification, and per Delta_G's suggestion, I'll try to explain the difference between an array and a collection of variables. Each variable you define is mapped by the compiler (technically, the linker) to a memory area. You can think of the variable names as convenient names assigned to those memory locations. If you write:

Bounce rmd0(48, 10), rmd1(47, 10), rmd2(46, 10), ...;

You get:

 ┌───────┐ ┌───────┐ ┌───────┐
rmd0: | | rmd1: | | rmd2: | | ...
 └───────┘ └───────┘ └───────┘

In the picture above, the boxes are the memory areas. They are large enough to hold a Bounce object, i.e. their size is sizeof(Bounce). Each one has a name. You have no control over where, within the memory, those variables are allocated: it's the linker's call.

In contrast, when you declare an array, you get a single variable which is mapped to a contiguous memory area large enough to hold the whole array:

Bounce rmd[6] = { ... };

Gives:

 ┌───────┬───────┬───────┬───────┬───────┬───────┐
rmd: | | | | | | |
 └───────┴───────┴───────┴───────┴───────┴───────┘

The individual cells do not have a name, and you instead use indices to access them. For instance, rmd[0] references the first cell. Please, note that in this example there is no variable named rmd0: if you try to use that identifier the compiler will complain it is not defined. Again, an array is not a "collection of variables": it is a single variable.

The array cells do behave in some sense much like individual variables (they are called lvalues), as you can use rmd[0] in the same way you would have used rmd0 in the previous code. The point of using an array is that the indices do not need to be literals: you can use a variable instead (rmd[i], where i is a variable), which comes handy when you want to loop over all the cells.

Edgar pointed out that I can write the variable rmd3 by int i = 3 and rmd[i].

I hope it is now clear that this is not the case. There is no variable named rmd3 unless you create it explicitly. Declaring an array named rmddoes not create such a variable.

[Can I] "form" a variable by "characters"?

Your question is not very clear, but my guess is you are talking about computed variable names. This is a programming technique where you access a variable by computing its name at run time. For example, you combine the strings "rmd" and "3" in order to build the name of the variable "rmd3". Then you use this computed name to access the variable that has this name.

Computed variable names are quite often supported by interpreted languages. For example, in PHP this is called variable variables:

$foobar = 42; // the variable we want to access
$start = "foo"; // one piece of the name
$end = "bar"; // the other piece
$name = $start . $end; // build the name from its pieces
print $name . "\n"; // prints the variable name: "foobar"
print $$name . "\n"; // prints the variable's value: "42"

Computed variable names are not supported by C++, which is the language you use to program an Arduino. And for a good reason: when the compiler translates your program to machine code, the names of the variables are lost, they do not make their way to the actual Arduino. And this is a good thing, as you would not want those names to consume memory on the microcontroller.

Note that the names are present in the .elf file, as they could be useful for debugging. If you were programming for a PC, you program could in principle look into the file and find those names. On Linux you would do that with the dlopen() and dlsym() functions, from the libdl library. The libdl technique is, however, very far from the capabilities of your typical Arduino, orders of magnitude more complex than a simple array, and perfectly useless for your use case.

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

The question is somewhat confused, but I think I got what you mean. Your code suffers from too much repetition. You only showed the handling of two selectors, but you want to handle 6 of them. Repeating all the logic 6 times would make the code unwieldy and hard to maintain. So you want to put the logic in a function and just call that function six times.

I actually only had to pass the number to the function, like "3" to change some Variables and Char Strings accordingly

You do not need to pass the number as a string: you can use Serial.print() to format the number instead. And you do not need to write a function either: you can just put a for loop inside the loop() function:

const int rmd_count = 6;
Bounce rmd[rmd_count] = {
 Bounce(48, 10), // rotary selector on pos. 0
 Bounce(47, 10), // rotary selector on pos. 1
 Bounce(46, 10), // rotary selector on pos. 2
 Bounce(45, 10), // rotary selector on pos. 3
 Bounce(44, 10) // rotary selector on pos. 4
 Bounce(43, 10) // rotary selector on pos. 5
};
void loop() {
 for (int i = 0; i < rmd_count; i++) {
 rmd[i].update();
 if (rmd[i].fallingEdge()) {
 Serial.print("rmd[");
 Serial.print(i);
 Serial.println("] = 1");
 rotary_mode = i;
 Serial.print("rotary_mode = ");
 Serial.println(i);
 }
 if (rmd[i].risingEdge()) {
 Serial.print("rmd[");
 Serial.print(i);
 Serial.println("] = 0");
 rotary_mode = 0;
 Serial.println("rotary_mode = 0");
 }
 }
}

The key to using for loops is to structure your data in arrays, instead of collections of variables named with numbers. Thus, instead of rmd3 you would use rmd[3]. Note that array indices start at zero.

Obviously, you could put the body of the for loop inside a function, but at this point that would not help much in simplifying the code.

lang-cpp

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