Solved

C++: Passing bool variable to a function

Posted on 2014-07-22
21
3,874 Views
Last Modified: 2014-07-24
I have a code which looks like foll.
//declaration
bool IsMultiple( int* bOK, bool bMultiple = false ) 
//implementation
#include <iostream>
#include <iomanip>
bool IsMultiple( int* bOK, bool bMultiple )
{
  *bOK = false;
   //some processing
    bMultiple = true;
   if(bMultiple)
   {
        *bOK = true;
        return true;
   }
   return false;
}
 
int main()
 {
 
    bool bMultiple = false;
    bool bRet = IsMultiple(bMultiple );
    std::cout << bMultiple << std::endl; // prints always false, even if set true in function
    //call again
    bool cRet = IsMultiple(); //bMultiple is default
    std::cout << bMultiple << std::endl;  // same deal
    return 0;
}

Open in new window

The function changes the value of bool argument, however back in main function bool variable reverts to original value(false). What is happening? How to fix?
Thanks.
0
Comment
Question by:vakils
  • 9
  • 8
  • 3
  • +1
21 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
This snippet should not even compile, You are declarin a function that takes an 'int*', but you ar passing  'bool' by value. If you meant to pass its address as a pointer, you should use

//declaration
bool IsMultiple( bool* bOK, bool bMultiple = false );

//...

bool bRet = IsMultiple(&bMultiple ); // <-- important: use '&' here

Open in new window


which  I assume would fix your initial problem.

Also, the statement

bool cRet = IsMultiple(); //bMultiple is default

Open in new window


will not compile, since the 2nd parameter has a default, but the 1st hasn't.

To sum that up, this here should do what you want:

//declaration
bool IsMultiple( bool* bOK, bool bMultiple = false );
//implementation
#include <iostream>
#include <iomanip>
bool IsMultiple( bool* bOK, bool bMultiple )
{
  *bOK = false;
   //some processing
    bMultiple = true;
   if(bMultiple)
   {
        *bOK = true;
        return true;
   }
   return false;
}
 
int main()
 {
 
    bool bMultiple = false;
    bool bRet = IsMultiple(&bMultiple );
    std::cout << bMultiple << std::endl; 
    //call again
    bool cRet = IsMultiple(&bMultiple); //bMultiple is default - but NOT the 1st parameter, only the 2nd one
    std::cout << bMultiple << std::endl;  
    return 0;
}

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
BTW, you might want to consider using a reference instead of a pointer here, e.g.

//declaration
bool IsMultiple( bool& bOK, bool bMultiple = false );
//implementation
#include <iostream>
#include <iomanip>
bool IsMultiple( bool& bOK, bool bMultiple )
{
   bOK = false;
   //some processing
    bMultiple = true;
   if(bMultiple)
   {
        bOK = true;
        return true;
   }
   return false;
}
 
int main()
 {
 
    bool bMultiple = false;
    bool bRet = IsMultiple(bMultiple ); // now you can call it without using '&'
    std::cout << bMultiple << std::endl; 
    //call again
    bool cRet = IsMultiple(bMultiple); //bMultiple is default - but NOT the 1st parameter, only the 2nd one
    std::cout << bMultiple << std::endl;  
    return 0;
}
                    

Open in new window

0
 

Author Comment

by:vakils
Comment Utility
bool cRet = IsMultiple(bMultiple); //bMultiple is default - but NOT the 1st parameter, only the 2nd on
You are passing bMultiple by value, where is reference? bMultiple will get assigned to first param(bOK) as it is not default and so I won't be able to get bMultiple value processed from function. The function is designed so that it could return with bOK true, but bMultiple false.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>> You are passing bMultiple by value, where is reference?

References don't need to be declared as such when calling the function in question, the declaration will take care of the correct behaviour, so you won't have to worry. BTW, did the 1st snippet that still uses pointers work for you?
0
 

Author Comment

by:vakils
Comment Utility
Yes, the first one worked. The second didn't.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Weird, it gave me the same output when I ran it here... and it still does after double checking that with the above snippets. Is there anything you might have changed?
0
 

Author Comment

by:vakils
Comment Utility
I will try with a small app and check.  Shouldn't function be declared as
IsMultiple (bool& bOK, bool& bMultiple = false);
0
 
LVL 8

Expert Comment

by:Subrat (C++ windows/Linux)
Comment Utility
Can you paste the complete code here? It seems you are doing something wrong there.
JKR's suggestion is valid.
0
 
LVL 8

Expert Comment

by:Subrat (C++ windows/Linux)
Comment Utility
>> Shouldn't function be declared as IsMultiple (bool& bOK, bool& bMultiple = false);
No.
It should be
bool IsMultiple (bool& bOK, bool bMultiple = false);
If using reference as parameter to a function, you can't use default argument for that parameter. There will be a conversion issue from bool to bool&.
0
 
LVL 8

Expert Comment

by:Subrat (C++ windows/Linux)
Comment Utility
To understand, why conversion is not possible, consider following examples.

bool fun(int* p); // Valid
bool fun2(int* p = 0); // Valid - here it's pointing to nothing
bool fun2(int* p = 1); // Invalid, here we are trying to assign a integer to an address where an address is expected

So if really you want this feature, you need to do a type casting. I hope type casting  will not throw any error.(Not tested)

FYI: Reference is nothing but a constant pointer.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 32

Expert Comment

by:sarabande
Comment Utility
to add to above comments:

to pass bOk as an output argument seems to be unnecessary. the ok should be the return value. as you want to have the bMultiple returned you need to define it and can initialize it with the default:

// function declaration
bool IsMultiple(bool & bMultiple);

....
bool bMultiple = false;  
bool bok = IsMultiple(bMultiple);  

Open in new window

that looks better now but is still bad code. an "Is..."-function should not return an ok but should return the answer to the the "Is..." question. all other is badly readable and should be avoided. so your final code should be like

bool IsMultiple(int num1, int num2)
{
       bool bMultiple = false;
       if (num1 != 0 && num2 != 0)
       {
              int d = num2/num1;
              bMultiple = (d*num1 == num2);
       }
        return bMultiple;
}

Open in new window


now the IsMultiple is well-defined and could be used like

if (IsMultiple(6, 18))
{
      ...

Open in new window


Sara
0
 

Author Comment

by:vakils
Comment Utility
JKR,
Your code works because bMultiple gets assigned to bOK in function, which  takes &bOK and that arg is not default. The correct version of your code should be below, which shows the original behavior and my problem: bMultiple reverts back to false (original value).
//declaration
bool IsMultiple( bool& bOK, bool bMultiple = false );
//implementation
#include <iostream>
#include <iomanip>
bool IsMultiple( bool& bOK, bool bMultiple )
{
   bOK = false;
   //some processing
    bMultiple = true;
   if(bMultiple)
   {
        bOK = true;
        return true;
   }
   return false;
}
 
int main()
 {
 
    bool bMultiple = false;
	bool bOK = false;
    bool bRet = IsMultiple(bOK, bMultiple ); // now you can call it without using '&'
    std::cout << "bOK=" << bOK << "bMultiple=" <<bMultiple << std::endl; 
    //call again
    bool cRet = IsMultiple(bOK); //bMultiple is default - but NOT the 1st parameter, only the 2nd one
    std::cout << "bOK=" << bOK << std::endl;  
    return 0;
}

Open in new window

                   
Output
bOK=1bMultiple=0
bOK=1

Open in new window


If I define function:
bool IsMultiple( bool& bOK, bool& bMultiple = false );      

Open in new window

 
I get compilation error.
How would you get around that?
0
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
Comment Utility
The reason that 'bMultiple' does not change is either code snippet is that you are effectively passing it by value, which will not reflect any changes in the calling function.

>>I get compilation error.
>>How would you get around that?

You can't use default parameters with references - that is because a default parameter basically means that the compiler provides an non-assignable value. The only way is to not use a default value, e.g.

bool IsMultiple( bool& bOK, bool& bMultiple);
//implementation
#include <iostream>
#include <iomanip>
bool IsMultiple( bool& bOK, bool& bMultiple )
{
   bOK = false;
   //some processing
    bMultiple = true;
   if(bMultiple)
   {
        bOK = true;
        return true;
   }
   return false;
}
 
int main()
 {
 
    bool bMultiple = false;
	bool bOK = false;
    bool bRet = IsMultiple(bOK, bMultiple ); 
    std::cout << "bOK=" << bOK << "bMultiple=" <<bMultiple << std::endl; 
    //call again
    bool cRet = IsMultiple(bOK, bMultiple); 
    std::cout << "bOK=" << bOK << std::endl;  
    return 0;
}
                                                        

Open in new window

0
 

Author Comment

by:vakils
Comment Utility
Why it works with pointers? What are the semantics between pointers and references ( as you can pass reference and modify that in function)
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Pointers and references are different concepts, even though they seem so similar, see e.g. http://en.wikipedia.org/wiki/Reference_(C++)#Relationship_to_pointers

Think of it as a logical link, whereas a pointer is a physical link to the memory area an object or variable resides in. This however implies some limitations, such as they cannot be used with default parameters in function calls.
0
 

Author Comment

by:vakils
Comment Utility
OK. Got it. Reference has to point to something. I found foll. workaround works:
bool bRetn = 1; //global scope
bool IsMultiple( bool& bOK,  bool& bMultiple = bRetn); // Now ref has something to refer to
0
 

Author Comment

by:vakils
Comment Utility
Subrat,
FYI: Reference is nothing but a constant pointer.
If that is so, how can we modify its value from a function?
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
It is not a 'constant pointer' - it's a link that cannot be 'reseated' (as the Wikipedia article puts it - or be reassigned, which would be my choice of wording). There are const references as well, but that also is different and you'd usually use that to pass a reference to 'something big' (i.e. an object too large to pass it via the call stack) without the option that the callee can modify it.
0
 

Author Comment

by:vakils
Comment Utility
OK. Thanks I learned a lot. Brushed up on C++. Reference is me, watching my boss's(object) seat(location). I cannot watch anybody else, boss can change (if not const) but seat remains same! How about that analogy. And of course I modified my code accordingly.
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Nice analogy ;-)

I wished you were able to present more than a model of your problem, so se would have addressed it more directly,,,
0
 

Author Comment

by:vakils
Comment Utility
It's a Visual Studio MFC application. So taking code out of context will not compile and would add to confusion. So I posted close approximation of the problem ( Whether reference can be a default parm) which would compile and I would understand your solution.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now