Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 5807
  • Last Modified:

C++: Passing bool variable to a function

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
Vakils
Asked:
Vakils
  • 9
  • 8
  • 3
  • +1
1 Solution
 
jkrCommented:
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
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
jkrCommented:
>> 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
 
VakilsDeveloperAuthor Commented:
Yes, the first one worked. The second didn't.
0
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
I will try with a small app and check.  Shouldn't function be declared as
IsMultiple (bool& bOK, bool& bMultiple = false);
0
 
Subrat (C++ windows/Linux)Software EngineerCommented:
Can you paste the complete code here? It seems you are doing something wrong there.
JKR's suggestion is valid.
0
 
Subrat (C++ windows/Linux)Software EngineerCommented:
>> 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
 
Subrat (C++ windows/Linux)Software EngineerCommented:
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
 
sarabandeCommented:
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
 
VakilsDeveloperAuthor Commented:
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
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
Why it works with pointers? What are the semantics between pointers and references ( as you can pass reference and modify that in function)
0
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
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
 
VakilsDeveloperAuthor Commented:
Subrat,
FYI: Reference is nothing but a constant pointer.
If that is so, how can we modify its value from a function?
0
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
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
 
jkrCommented:
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
 
VakilsDeveloperAuthor Commented:
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

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 9
  • 8
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now