I have the following code :
#include <cstdarg>
#include <iostream>
using namespace std;
class a {
};
void fun1(a& aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
void fun2(char *aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", (char *)0);
cout << "fun1" << endl;
fun1(a(), "1", "2", (char *)0);
getchar();
}
Everything works fine with fun2. However, fun1 will just crash.
May I know how can I prevent from crashing, at the same time able to use class reference as 1st parameter.
Currently, it prints :
fun2
1
2
fun1
then crash.
I wish
fun2
1
2
fun1
1
2
You can't use a reference parameter as the last named parameter with va_start. The reason is because va_start takes the address of the named parameter to find the location of the rest of the arguments. However, taking the address of a reference gives the address of the variable pointed at by the reference, not the address of the parameter itself. Your options are:
1) change the variable type from a reference to a pointer (or a non-reference if you are OK with a copy of the passed in variable).
2) Add an additional required parameter so that the reference isn't the last named parameter. The additional parameter can be a useful parameter, such as one of the char* you are going to pass to your particular function, or it can be a dummy variable you just ignore.
3) Change the definition of va_start. It's not recommended, but you can do it. See http://support.microsoft.com/kb/119394 for a non-portable redefinition.
It looks to me like you're crashing in fun2.
Because you're calling va_arg too many times and screwing up the stack.
You must only call va_arg the same number of times as there are parameters.
Both fun1 and fun2 terminate the loop when they encounter a NULL or 0 parameter. You are never passing one. Change main to:
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", NULL);
cout << "fun1" << endl;
fun1(a(), "1", "2", NULL);
getchar();
return 0;
}
Note I haven't compiled this, but it should work. You may have to follow janm's advice as well.
Update: I set down and thought about this again. You have to either:
Instantiate an object of type a inside of main and pass it or...
Following janm's advice and change a& aa in fun2 to a const& aa
When I tried to compile the original under g++, I was greeted with the following error:
error: invalid initialization of non-const reference of type 'a&' from a
temporary of type 'a'
error: in passing argument 1 of 'void fun1(a&, ...)'
Essentially, you cannot pass a temporary variable as a non-const reference. See this SO question and this Herb Sutter GotW for some of the gory details.
I'm sorry to hear this code doesnt work. I notice if fun2(aa is a ptr instead of a ref the code works. I also notice while trying to compile on gcc (via http://codepad.org/) you pass "a" into fun2 which is a char*. codepad/gcc complained about it not being a const char*. In codepad this code works. In my copy of VS2008 it crashes and 2010b2 as well.
My recommendation is to avoid va params but i'll assume you can't so i suggest not to use ref and use pointers. Or switch to gcc but i wouldnt do that unless there are no other (reasonable) option.
#include<cstdlib>
#include <cstdio>
#include <ios>
#include <iostream>
using namespace std;
class a {
};
void fun1(a& aa, ...)
{
//cout<< "sizeof" << sizeof(aa) << "&aa == " << &aa;
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
void fun2(const char *aa, ...)
{
va_list argp;
va_start(argp, aa);
char *p = 0;
while ((p = va_arg(argp, char *)) != 0) {
cout << p << endl;
}
va_end(argp);
}
int main()
{
cout << "fun2" << endl;
fun2("a", "1", "2", 0);
cout << "fun1" << endl;
a aa;
//cout<< "sizeof" << sizeof(aa) << "&aa == " << &aa;
fun1(aa, "1", "2", 0);
getchar();
}
You are passing a non-const reference to a temporary. Change the fun1 prototype to:
void fun1(a const& aa, ...)
Update:
Haven't used varargs for a long time, missed that a terminating parameter wasn't being passed. See D. Shawley's answer; you must pass a terminating parameter if you're going to use that as your interface.
Related
This question already has answers here:
When I change a parameter inside a function, does it change for the caller, too?
(4 answers)
Closed 4 years ago.
I know call by pointers in which we pass address of variables.Something like this:
void swap(int *x, int *y)
{
int temp;
temp = *x; /* save the value at address x */
*x = *y; /* put y into x */
*y = temp; /* put x into y */
return;
}
swap(&a, &b);
And also call by reference,in both of these methods the changes made in the function are reflected in actual arguments' variable.
But why are actual parameters passed in this case of call not changed:
#include <iostream>
using namespace std;
void foo(int* c){
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout<<&c<<endl; //0x7ffe1a74f3b0
foo(c);
cout<<*c<<endl;//5
cout<<&c<<endl;//0x7ffe1a74f3b0
}
Here c passed to foo() is address of a.So how this is call by value.
Here c should have printed garbage value according to me.Please explain what has happened here.
And also call by reference, in both of these methods the changes made in the function are reflected in actual arguments' variable.
There is an important difference, though: the changes are always made to whatever is referenced/pointed to, never to the reference/pointer itself (modifying a reference is impossible in general).
That is why assigning c a new value inside foo has no effect on c outside foo: the pointer passed to a function is copied.
If you need to modify the pointer, you need to add another level of dereference by passing a pointer reference or a pointer to a pointer.
Following on from comments, the variable c defined in function main is a different variable to the parameter c of function foo. If you want foo to be able to modify main's c, that is modify the address that c's pointer type holds, then you need to pass either a reference or pointer to c to the function instead.
Here is an example that shows the difference between passing c by value (as int *), or by reference (as int ** or int *&). Don't be fooled by the fact that int * is a pointer type, that means that it can receive an int by reference or an int * by value. And since main's c is int * rather than int, main c is being passed by value.
Note the differences in how the functions are called (whether c needs the address operator & in the function call) and the outcome of each function.
#include <iostream>
using namespace std;
void foo_int_ptr(int* c)
{
c=c+1;
}
void foo_int_ptr_ptr(int** c)
{
*c=*c+1;
}
void foo_int_ptr_ref(int*& c)
{
c=c+1;
}
int main()
{
int a=5;
int *c=&a;
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ptr(&c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
foo_int_ptr_ref(c);
cout << "&c=" << &c << ", c=" << c << ", *c=" << (c==&a ? std::to_string(*c) : std::string("INVALID PTR")) << endl;
}
Output:
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808ac, *c=5
&c=0x7e02d81808b8, c=0x7e02d81808b0, *c=INVALID PTR
&c=0x7e02d81808b8, c=0x7e02d81808b4, *c=INVALID PTR
there is a mistake in your thinking about this ..
int *c = &a;
this doesn't mean that c "contains" address of a, this means that c is a pointer TO the address of a. Passing a pointer to foo() will not do anything.
This question already has answers here:
Calling a function pointer whose assigned function has less arguments then the pointer type
(2 answers)
Closed 7 years ago.
take a look at the following example:
#include <iostream>
#include <string.h>
void Func1(int x)
{
std::cout << "I'm function 1: " << x << std::endl;
}
void Func2(int x, const char* str)
{
std::cout << "I'm function 2: (this is arg1: " << x << " - args2: " << str << ")" << std::endl;
}
uintptr_t GetProcAddress(const char* _str)
{
if (strcmp(_str, "func1") == 0)
{
return reinterpret_cast<uintptr_t>(Func1);
}
else
{
return reinterpret_cast<uintptr_t>(Func2);
}
}
int main()
{
typedef void(*PROCADDR)(int, const char*);
PROCADDR ext_addr = nullptr;
ext_addr = (PROCADDR)GetProcAddress((const char*)"func1");
//call the function
ext_addr(10, "arg");
std::cin.get();
return 0;
}
We are basically calling Func1 with 2 arguments and can switch to call Func2 with the same args and everything works as intended.
Of course the address of both the arguments are always pushed on to the stack even though the second one is never used by the function itself.
Now I understand that the above code should never be used in production-code but my main question is, can the above code cause UB or is the code always expected to act like that?
Best regards
xx
Yes, it's undefined behavior. From [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling
a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined.
From what I understand, this should work:
const char* x = "x";
std::cout << x << std::endl;
Passing x into this function:
void myClass::passAsVoid(void* v) {
std::cout << (const char*)v << std::endl;
}
The first example prints "x";
The second example prints "\350\224A";
I want to learn what's going on, and the correct approach to do this!
The actual code:
float delay = 1;
std::string txt = "random filler text that is not lorum ipsum";
for (int i = 0; i < txt.length(); ++i) {
const char* x = "x";
std::cout << x << "code1" << std::endl;
CCSequence* seq = CCSequence::create(CCDelayTime::create(i*delay),
CCCallFuncND::create( this, callfuncND_selector(OverWorldView::setString), (void*)x ),
NULL);
this->runAction(seq);
}
Callback function:
void OverWorldView::setString(void* x) {
std::cout << (const char*)x << "code2" << std::endl;
label1->setString( (const char*)x );
}
I'm using cocos2dx 2.1.4
It looks like you are not using the API correctly.
The documentation says you need to use a SEL_CallFuncND type callback, which receives two arguments, not one.
For everyone's convenience, callfuncND_selector is a macro that hides a static_cast, or probably even a C-style cast (could not find other API versions online) which lets you use just about anything as a callback without getting any compilation errors. Pure joy.
This won't even compile because you're passing a const pointer to a function which accepts a non-const pointer. If you can't change the type of the callback then instead of passing a string literal, pass a character array.
char buffer[100];
callback(buffer); //buffer decays to char* which is implicitly converted to void*
If you can change the type of the callback though then modify the parameter to be const void*.
I would like to use parameter in C++ to store back whatever value/object.
In this example, I try to store the value from the global variable as a simplified example.
This code doesn't work,
int value = 20;
void returnPointer2(int* hello)
{
hello = &value;
}
// It changes nothing
int value2 = 100;
returnPointer2(&value2);
cout << value2 << endl;
as I needed double pointer.
void returnPointer3(int** hello)
{
*hello = &value;
}
int* vp2 = new int();
*vp2 = -30;
returnPointer3(&vp2);
cout << *vp2 << endl; // expects 20
I reminded of the reference, and I can use pointer reference to get the same result.
void returnPointer4(int* & hello)
{
cout << "value : " << value;
hello = &value;
}
int* vp3 = new int();
*vp3 = -130;
returnPointer4(vp3); // also expects 20, but much simpler to use
cout << "better : " << *vp3 << endl;
I tried with double &, and it compiles.
void returnPointer5(int&& hello)
{
cout << "value : " << value;
hello = value;
}
However, it doesn't compile with the input of integer variable.
int vp4 = 123;
returnPointer5(vp4); // also expects 20, but even more simpler to use
cout << "best : " << vp4 << endl;
This is an error message.
pointer_return.cpp:31:6: error: initializing argument 1 of 'void returnPointer5(int&&)'
void returnPointer5(int&& hello)
I happened to know about move, and it works with this code.
int vp4 = 123;
returnPointer5(move(vp4)); // also expects 20, but much simpler to see
cout << "best : " << vp4 << endl;
What's the magic/logic behind this move function?
There is a lot of stuff getting mixed in here, but to keep it simple I'll address your root question.
&& is nothing at all like **.
&& is an rvalue reference, while ** is a pointer to a pointer.
As a second point, you are declaring in your function name what you want to do: returnPointer4.
You want to have a pointer to an integer returned back. int*& is the correct syntax for having a reference to a pointer.
Reading over your question again, why don't you use the following:
int& returnGlobalReference() {
return value;
}
Then in your other function:
int& value2 = returnGlobalReference();
The first attempt makes the classic mistake of passing a pointer by value, modifying its address in the function and expecting what it points to to change.
As mentioned in the comments,
void returnPointer2(int* hello)
{
hello = &value; // don't do this, it only modifies what the
// pointer hello, which resides in the stack, points to
*hello = value; // do this instead. even though hello still resides in the
// stack, you're modifying the location that hello points to,
// which was your original intention
}
why do you want to pass pointers however? is the static variable not available when you call the function? (perhaps, different files?)
The magic of std::move is:
The actual declaration for std::move is somewhat more involved, but at its heart, it's just a static_cast to an rvalue reference.
Taken from here.
As Jeffery Thomas already said, a && is not a reference to a reference, but a reference to a rvalue.
This question is regarding Function Stack Creation.
Suppose we create a function fn(int a,char b) and call from main fn(A,B) , in this case when the function is called a fn. stack is created with return address, Stack pointer (etc) where local variables and parameters are created and on return is destroyed.
I have a few questions:
1) For our parameterized constructor suppose
myClass{
int a;
char c;
public:
myClass(int a,char c)
{
this->a=a;
this->c=c;
}
};
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c.
2) Now suppose we are calling by reference : my function is fn(int* a,char* b) or fn(int& a, char& b) and calling from our main by fn(&A,&B) and fn(A,B) respectively , in this case also, a function stack will be created with return address,SP etc. My question is that, will a local pointer or reference be created on stack in this case (i.e. creating a local copy of pointer or reference that will point to the passed object). Or is it that no local copy of object is created and the original object pointed by the pointer or the refence is directly passed?
3) Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
Thanks
EDIT
#include <iostream>
using namespace std;
void fn(int , char);
//void fn (int* a, char* c);
void fn (int& a, char& c);
int main()
{
int a=10;
char c= 'c';
cout << "Inside main()" << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
fn(a,c);
//fn(&a,&c);
fn(a,c);
return 0;
}
void fn (int a, char c)
{
int tempInt;
char tempChar;
cout << "\n\nInside Call By Value Function " << endl;
cout << hex << "&a : " << &a << endl;
cout << hex << "&c : " << (int *)&c << endl;
cout << hex << "&tempInt : " << &tempInt << endl;
cout << hex << "&tempChar : " << (int *)&tempChar << endl;
}
/*void fn (int* a, char* c)
{
cout << "\n\nInside Call By Pointer Function " << endl;
cout << hex << "*a : " << a << endl;
cout << hex << "*c : " << (int*) c << endl;
}
*/
void fn (int& a, char& c)
{
cout << "\n\nInside Call By Reference Function " << endl;
cout << hex << "*a : " << &a << endl;
cout << hex << "*c : " << (int*) &c << endl;
}
Output:
$ make
g++ -Wall Trial.cpp -o Trial
Trial.cpp: In function `int main()':
Trial.cpp:19: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
Trial.cpp:21: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note: void fn(int&, char&)
make: *** [Trial] Error 1
does the constructor myClass(int a,char c) also create its function stack and create local variables a and c
Yes, a function stack is created but a and c are not local variables to the function stack, they are member variables and there lifetime does not end with the end of the constructor. They remain alive throughout the lifetime of the class instance whose member they are.
Or is it that no local copy of object is created and the original object pointed by the pointer or the reference is directly passed?
This is known as pass by reference. The two ways are:
Passing the address of the object or
Pass the object by a reference
In either case the copy of the object is not created. The actual object can be modified within the function, In case 1 the pointer in the function points to the address of the object being passed while in case 2 the reference argument is merely an alias to the object being passed.
Can we overload a function like fn(int& a,char& b) and fn(int a,int b)?
No, you cannot because the compiler cannot understand which function version you intend to call when you call it as:
int i = 10;
int j = 20;
fn(i,j);
I misread, as fn(int& a,int& b) and fn(int a,int b) instead of fn(int& a,char& b) and fn(int a,int b).
Ofcourse you can. They have distinct types and hence qualify as valid overloaded functions.
To begin with, your concept is slightly incorrect.
i.e. Stack is not created with a function call. Rather each thread of execution has its own stack already. It is even there when a single main is called. However an ACTIVATION record is pushed on the stack when a function is called. And the same is popped when returning from a function.
So for
Stack is already there and an activation record is pushed on the stack for each function call. The variables live throughout the lifetime of the object.
If your function takes a pointer as argument (i.e. call by reference), there will be a pointer variable pushed on the stack which is passed the address of the original variable. The original variable remains intact and modifying its value via pointer would change the original variable.
You can only overload functions when their signatures are different. This means type, number or order of parameters. In the e.g. you quoted, it is not possible to differentiate whether a passed int is a variable or it is an address of a variable. Hence this overload won't work.
EDIT: Point 3 above has as slight mistake. The e.g. quoted in question has second parameter different and hence qualifies as valid overload. Note that the criteria is not just the name of data type (i.e. int vs. int * is also different types), but rather the fact that given an input value, compiler should be able to differentiate and chose which overloaded version to call.