I'm working on building a watch based on the Arduino/ATMega. The primary goal for now is to switch between "modes” (different functions) by pressing a button on the side. Initially, I had a long if statement like this:
if (counter == 0)
mode1();
enter code
else if (counter == 1)
mode2();
.... Repeat....
But that seems inefficient. So, I tried to make an array of the functions without actually calling them, and then call the indexed function later. The code segment is as follows (Apologies for the mess, it’s very much a WIP)
int Modes[3] = {showTime,flashlight,antiAnxiety} //these are all void functions that are defined earlier.
int scroller(){
int counter = 0;
int timeLeft = millis()+5000;
while (timer <= millis()){
...more code...
}
Modes[counter]();
}
However, when I try to compile that, I get an error:
Error: expression cannot be used as a function.
That logic works in Python, so I’m assuming there’s a concept I don’t know that gets abstracted away in higher-level languages. I’m quite willing to learn it, I just need to know what it is.
The type is wrong - instead of int you need void (*)() as type (because you have an array of void someFunction() function pointers, not an array of integers - and while the former can be converted to the latter in a way, as memory address, you cannot call an integer).
void (*Modes[3])() = {showTime, flashlight, antiAnxiety};
This code becomes easier to understand with a type definition:
typedef void (*func_type)();
func_type Modes[3] = {showTime, flashlight, antiAnxiety};
I am using fftw for a fourier transform in c++. There is the standard data type fftw_complex, which is basically a double[2]. I want to make an array of fftw_complex. I do this with
typedef fftw_complex fftw_complex_16[65536];
I set everything to zero in the array. Then I have another function which should check if an fftw_complex_16 is empty.
bool is_empty_fftw_complex_16(fftw_complex_16 *thecomplex){
std::cout<<"Test\n"<<::vowels["a:"][0][0]<<std::endl;
for (unsigned long i=0; i<65536; i++){
if(thecomplex[i][0] != 0 || thecomplex[i][1] != 0){
std::cout<<"Huch!"<<i<<std::endl;
std::cout<<thecomplex[i][0]<<" -- "<<thecomplex[i][1]<<std::endl;
std::cout<<*thecomplex[i][0]<<" -- "<<*thecomplex[i][1]<<std::endl;
return 1;
}
}
return 0;
}
Forget about the couts, they are only for debugging. The only thing the function should do is return true if the array the pointer argument points to is empty and false otherwise. It does not work. The function says the array is not empty when it is! Please help, what am I doing wrong?
The problem seems to be this
bool is_empty_fftw_complex_16(fftw_complex_16 *thecomplex){
which from your description should really be this
bool is_empty_fftw_complex_16(fftw_complex *thecomplex){
but it's hard to be completely sure because you didn't post the code which sets up this array and calls this function, which unfortunately is a crucial thing to miss out.
Something like this would be the correct way to call the function
fftw_complex_16 array;
...
is_empty_fftw_complex_16(array);
I'm guessing that you combined the incorrect declaration above with this incorrect call.
fftw_complex_16 array;
...
is_empty_fftw_complex_16(&array);
This compiles but doesn't do what you wanted.
I would like to know if there is any clever trick how to safely convert integer into enum. Before you vote that this is duplicate, I'm not asking about how to convert (int i; Enum e = static_cast<Enum>(i) is easy). I'm asking how to do it safely, verifying that resulting value really is in the enum.
Following code
enum class E {
A = 1,
B = 2
};
int main(int, char **) {
int i = 3;
E e = static_cast<E>(i);
}
will compile (AFAIK) but e will not contain valid value from the enum. Best way I came up with is something like
switch (i) {
case 1:
return E::A;
case 2:
return E::B;
default:
throw invalid_argument("");
}
which 1) doesn't look very smart 2) doesn't scale so well. I could probably put together some macros to make this easier but it still looks dumb.
So is there any "standard" way to do it?
Thanks
If you do not have to convert the numeric value as well, I'd suggest something like
switch (i)
{
case static_cast<int>(E::A):
case static_cast<int>(E::B):
return static_cast<E>(i);
default:
throw invalid_argument("");
}
At least that prevents some common mistakes like forgetting to change either the case or the return value or simply looking up the wrong numeric value. Also it's much more refactoring friendly (think about changing the numeric value - after all you define an enum so that you don't have to change the value in more than one place).
Unfortunately that still isn't very nice, but its the best way I know. Well, unless you want to use X macros.
I cant get enum this to work properly on Windows. While compiling on linux it returns expected value, but on windows it returns some random number.
typedef enum wezly {
elektrownie1,
konwencjonalne1,
niekonwencjonalne1,
weglowa1,
jadrowa1,
sloneczna1,
wiatrowa1,
geotermiczna1,
gazowa1,
wodna1,
maremotoryczna1,
maretermiczna1
};
wezly wybor_wezla(string opcja)
{
string bb;
bb = opcja;
if ((bb.compare("[elektrownie]")==0)||(bb.compare("[ELEKTROWNIE]")==0))
return elektrownie1;
else if ((bb.compare("[konwencjonalne]")==0)||(bb.compare("[KONWENCJONALNE]")==0))
return konwencjonalne1;
else if ((bb.compare("[gazowa]")==0)||(bb.compare("[GAZOWA]")==0))
return gazowa1;
else if ((bb.compare("[wodna]")==0)||(bb.compare("[WODNA]")==0))
return wodna1;
// (and so on...)
}
int main()
{
cout << wybor_wezla("[gazowa]");
}
When on linux i get 7, on windows its some random number....
Why can that be ?
It's actually broken here (after looking at the link you gave in the comments):
bb=opcja.substr((opcja.find_first_of("[")),(opcja.find_first_of("]"))-1);
This results in extracting a string like "[whateve" if the input is "... [whatever] ...".
What I think you mean is:
bb=opcja.substr((opcja.find_first_of("[")),(opcja.find_first_of("]"))-opcja.find_first_of("[")+1);
Which results in extracting a string like "[whatever]" from the input.
The original code, given the input "[gazowa]", will compare "[gazow" to various strings, none will match, and the end of the function will be reached without hitting a return statement.
This results in undefined behaviour. Hence your result of 7 on linux, and some other value on windows, when [gazowa] ought to give you 8.
You also need to do something more sensible to handle the case where none of your strings are matched, i.e. if the end of wybor_wezla is reached. What you do in that case is up to you, but as a start I'd at least put a print statement in there so you know when nothing's matched.
Your code is missing a final else clause:
wezly wybor_wezla(string opcja)
{
if(...)
return ...;
else if(...)
return ...;
else if(...)
return ...;
// No final else!
}
When none of the if clauses are true, it falls off the end of the function without returning a value, which is Undefined Behavior. In this case, it's returning a garbage value, but worse stuff could happen.
Your first action should be to add a final else clause. This can return a default value, an error code, throw an exception, abort(), etc., but it cannot do nothing. If you know the value has to be one of a limited set of things, you could change the final else if into just an else and assume that if it's not the first N-1 things, it's the Nth thing.
Once you've done that, you need to figure out why your data isn't falling into one of the expected cases and fix that.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Inadvertent use of = instead of ==
C++ compilers let you know via warnings that you wrote,
if( a = b ) { //...
And that it might be a mistake that you certainly wanted to write:
if( a == b ) { //...
But is there a case where the warning should be ignored, because it's a good way to use this "feature"?
I don't see any code clarity reason possible, so is there a case where it’s useful?
Two possible reasons:
Assign & Check
The = operator (when not overriden) normally returns the value that it assigned. This is to allow statements such as a=b=c=3. In the context of your question, it also allows you to do something like this:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
//if x is equal to true, return 4
if (global=x)
return 4;
//otherwise return 3
return 3;
}
...which is equivalent to but shorter than:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
global=x;
//if x is equal to true, return 4
if (global==true)
return 4;
//otherwise return 3
return 3;
}
Also, it should be noted (as stated by Billy ONeal in a comment below) that this can also work when the left-hand argument of the = operator is actually a class with a conversion operator specified for a type which can be coerced (implicitly converted) to a bool. In other words, (a=b) will evaulate to true or false if a is of a type which can be coerced to a boolean value.
So the following is a similar situation to the above, except the left-hand argument to = is an object and not a bool:
#include <iostream>
using namespace std;
class Foo {
public:
operator bool (){ return true; }
Foo(){}
};
int main(){
Foo a;
Foo b;
if (a=b)
cout<<"true";
else
cout<<"false";
}
//output: true
Note: At the time of this writing, the code formatting above is bugged. My code (check the source) actually features proper indenting, shift operators and line spacing. The <'s are supposed to be <'s, and there aren't supposed to be enourmous gaps between each line.
Overridden = operator
Since C++ allows the overriding of operators, sometimes = will be overriden to do something other than what it does with primitive types. In these cases, the performing the = operation on an object could return a boolean (if that's how the = operator was overridden for that object type).
So the following code would perform the = operation on a with b as an argument. Then it would conditionally execute some code depending on the return value of that operation:
if (a=b){
//execute some code
}
Here, a would have to be an object and b would be of the correct type as defined by the overriding of the = operator for objects of a's type. To learn more about operator overriding, see this wikipedia article which includes C++ examples: Wikipedia article on operator overriding
while ( (line = readNextLine()) != EOF) {
processLine();
}
You could use to test if a function returned any error:
if (error_no = some_function(...)) {
// Handle error
}
Assuming that some_function returns the error code in case of an error. Or zero otherwise.
This is a consequence of basic feature of the C language:
The value of an assignment operation is the assigned value itself.
The fact that you can use that "return value" as the condition of an if() statement is incidental.
By the way, this is the same trick that allows this crazy conciseness:
void strcpy(char *s, char *t)
{
while( *s++ = *t++ );
}
Of course, the while exits when the nullchar in t is reached, but at the same time it is copied to the destination s string.
Whether it is a good idea, usually not, as it reduce code readability and is prone to errors.
Although the construct is perfectly legal syntax and your intent may truly be as shown below, don't leave the "!= 0" part out.
if( (a = b) != 0 ) {
...
}
The person looking at the code 6 months, 1 year, 5 years from now, at first glance, is simply going to believe the code contains a "classic bug" written by a junior programmer and will try to "fix" it. The construct above clearly indicates your intent and will be optimized out by the compiler. This would be especially embarrassing if you are that person.
Your other option is to heavily load it with comments. But the above is self-documenting code, which is better.
Lastly, my preference is to do this:
a = b;
if( a != 0 ) {
...
}
This is about a clear as the code can get. If there is a performance hit, it is virtually zero.
A common example where it is useful might be:
do {
...
} while (current = current->next);
I know that with this syntax you can avoid putting an extra line in your code, but I think it takes away some readability from the code.
This syntax is very useful for things like the one suggested by Steven Schlansker, but using it directly as a condition isn't a good idea.
This isn't actually a deliberate feature of C, but a consequence of two other features:
Assignment returns the assigned value
This is useful for performing multiple assignments, like a = b = 0, or loops like while ((n = getchar()) != EOF).
Numbers and pointers have truth values
C originally didn't have a bool type until the 1999 standard, so it used int to represent Boolean values. Backwards compatibility requires C and C++ to allow non-bool expressions in if, while, and for.
So, if a = b has a value and if is lenient about what values it accepts, then if (a = b) works. But I'd recommend using if ((a = b) != 0) instead to discourage anyone from "fixing" it.
You should explicitly write the checking statement in a better coding manner, avoiding the assign & check approach. Example:
if ((fp = fopen("filename.txt", "wt")) != NULL) {
// Do something with fp
}
void some( int b ) {
int a = 0;
if( a = b ) {
// or do something with a
// knowing that is not 0
}
// b remains the same
}
But is there a case where the warning
should be ignored because it's a good
way to use this "feature"? I don't see
any code clarity reason possible so is
there a case where its useful?
The warning can be suppressed by placing an extra parentheses around the assignment. That sort of clarifies the programmer's intent. Common cases I've seen that would match the (a = b) case directly would be something like:
if ( (a = expression_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression_with_zero_for_failure' (might be a function call, e.g.)
}
else if ( (a = expression2_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression2_with_zero_for_failure'
}
// etc.
As to whether writing this kind of code is useful enough to justify the common mistakes that beginners (and sometimes even professionals in their worst moments) encounter when using C++, it's difficult to say. It's a legacy inherited from C and Stroustrup and others contributing to the design of C++ might have gone a completely different, safer route had they not tried to make C++ backwards compatible with C as much as possible.
Personally I think it's not worth it. I work in a team and I've encountered this bug several times before. I would have been in favor of disallowing it (requiring parentheses or some other explicit syntax at least or else it's considered a build error) in exchange for lifting the burden of ever encountering these bugs.
while( (l = getline()) != EOF){
printf("%s\n", l);
}
This is of course the simplest example, and there are lots of times when this is useful. The primary thing to remember is that (a = true) returns true, just as (a = false) returns false.
Preamble
Note that this answer is about C++ (I started writing this answer before the tag "C" was added).
Still, after reading Jens Gustedt's comment, I realized it was not the first time I wrote this kind of answer. Truth is, this question is a duplicate of another, to which I gave the following answer:
Inadvertent use of = instead of ==
So, I'll shamelessly quote myself here to add an important information: if is not about comparison. It's about evaluation.
This difference is very important, because it means anything can be inside the parentheses of a if as long as it can be evaluated to a Boolean. And this is a good thing.
Now, limiting the language by forbidding =, where all other operators are authorized, is a dangerous exception for the language, an exception whose use would be far from certain, and whose drawbacks would be numerous indeed.
For those who are uneasy with the = typo, then there are solutions (see Alternatives below...).
About the valid uses of if(i = 0) [Quoted from myself]
The problem is that you're taking the problem upside down. The "if" notation is not about comparing two values like in some other languages.
The C/C++ if instruction waits for any expression that will evaluate to either a Boolean, or a null/non-null value. This expression can include two values comparison, and/or can be much more complex.
For example, you can have:
if(i >> 3)
{
std::cout << "i is less than 8" << std::endl
}
Which proves that, in C/C++, the if expression is not limited to == and =. Anything will do, as long as it can be evaluated as true or false (C++), or zero non-zero (C/C++).
About valid uses
Back to the non-quoted answer.
The following notation:
if(MyObject * p = findMyObject())
{
// uses p
}
enables the user to declare and then use p inside the if. It is a syntactic sugar... But an interesting one. For example, imagine the case of an XML DOM-like object whose type is unknown well until runtime, and you need to use RTTI:
void foo(Node * p_p)
{
if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
{
// this is a <body> node
}
else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
{
// this is a <span> node
}
else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
{
// this is a <div> node
}
// etc.
}
RTTI should not be abused, of course, but this is but one example of this syntactic sugar.
Another use would be to use what is called C++ variable injection. In Java, there is this cool keyword:
synchronized(p)
{
// Now, the Java code is synchronized using p as a mutex
}
In C++, you can do it, too. I don't have the exact code in mind (nor the exact Dr. Dobb's Journal's article where I discovered it), but this simple define should be enough for demonstration purposes:
#define synchronized(lock) \
if (auto_lock lock_##__LINE__(lock))
synchronized(p)
{
// Now, the C++ code is synchronized using p as a mutex
}
(Note that this macro is quite primitive, and should not be used as is in production code. The real macro uses a if and a for. See sources below for a more correct implementation).
This is the same way, mixing injection with if and for declaration, you can declare a primitive foreach macro (if you want an industrial-strength foreach, use Boost's).
About your typo problem
Your problem is a typo, and there are multiple ways to limit its frequency in your code. The most important one is to make sure the left-hand-side operand is constant.
For example, this code won't compile for multiple reasons:
if( NULL = b ) // won't compile because it is illegal
// to assign a value to r-values.
Or even better:
const T a ;
// etc.
if( a = b ) // Won't compile because it is illegal
// to modify a constant object
This is why in my code, const is one of the most used keyword you'll find. Unless I really want to modify a variable, it is declared const and thus, the compiler protects me from most errors, including the typo error that motivated you to write this question.
But is there a case where the warning should be ignored because it's a good way to use this "feature"? I don't see any code clarity reason possible so is there a case where its useful?
Conclusion
As shown in the examples above, there are multiple valid uses for the feature you used in your question.
My own code is a magnitude cleaner and clearer since I use the code injection enabled by this feature:
void foo()
{
// some code
LOCK(mutex)
{
// some code protected by a mutex
}
FOREACH(char c, MyVectorOfChar)
{
// using 'c'
}
}
... which makes the rare times I was confronted to this typo a negligible price to pay (and I can't remember the last time I wrote this type without being caught by the compiler).
Interesting sources
I finally found the articles I've had read on variable injection. Here we go!!!
FOR_EACH and LOCK (2003-11-01)
Exception Safety Analysis (2003-12-01)
Concurrent Access Control & C++ (2004-01-01)
Alternatives
If one fears being victim of the =/== typo, then perhaps using a macro could help:
#define EQUALS ==
#define ARE_EQUALS(lhs,rhs) (lhs == rhs)
int main(int argc, char* argv[])
{
int a = 25 ;
double b = 25 ;
if(a EQUALS b)
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
if(ARE_EQUALS(a, b))
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
return 0 ;
}
This way, one can protect oneself from the typo error, without needing a language limitation (that would cripple language), for a bug that happens rarely (i.e., almost never, as far as I remember it in my code).
There's an aspect of this that hasn't been mentioned: C doesn't prevent you from doing anything it doesn't have to. It doesn't prevent you from doing it because C's job is to give you enough rope to hang yourself by. To not think that it's smarter than you. And it's good at it.
Never!
The exceptions cited don't generate the compiler warning. In cases where the compiler generates the warning, it is never a good idea.
RegEx sample
RegEx r;
if(((r = new RegEx("\w*)).IsMatch()) {
// ... do something here
}
else if((r = new RegEx("\d*")).IsMatch()) {
// ... do something here
}
Assign a value test
int i = 0;
if((i = 1) == 1) {
// 1 is equal to i that was assigned to a int value 1
}
else {
// ?
}
My favourite is:
if (CComQIPtr<DerivedClassA> a = BaseClassPtr)
{
...
}
else if (CComQIPtr<DerivedClassB> b = BaseClassPtr)
{
...
}