I'm developing a c++ program that is dealing with addresses for different variables and functions.
When I compiled my program on a Linux based OS, all functions including the main get the address of 1 instead of an 8 digit hexa number like other variables, which did not happen in Windows.
I wrote this small piece of code to explain the issue
#include <iostream>
using namespace std;
void Function1();
void Function1(){
}
int main(){
int tmp;
void (*a) ()=&Function1;
cout<<a<<endl;
cout<<&Function1<<endl;
cout<<&main<<endl;
return 0;
}
for all 3 cout calls, the output is 1 instead of the virtual address.
The pointer gets converted to another type, bool, because it is a function pointer and there are no overloads of operator<< in the <iostream> library for function pointers (because there are an infinite number of such types). The pointer points to some non-zero address because it has been initialized with the address of the function - so it gets converted to 1 (only 0x0 address would give you boolean 0).
Solution
To assert correct behavior, you should cast the pointer to void* so you can use the operator<< overload for void*:
ostream & operator <<( ostream &, const void * );
Example:
void Function1(){}
int main() {
void ( *a) () = &Function1;
cout << ( void*)( a) << endl;
/* or better - being explicit about harshness of this design */
cout << reinterpret_cast< void*> ( a) <, endl;
}
http://ideone.com/Fne4Mu
C++ Standard n3337 § 4.12 Boolean conversions [conv.bool]
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
<< has no standard overload taking a function pointer; so instead, the pointer is converted to bool (since that's a legitimate implicit conversion), giving 1, or true if you've used the std::boolalpha manipulator on the stream.
If you want the address, you'll have to explicitly convert it to an object pointer:
std::cout << reinterpret_cast<void*>(&Function1) << std::endl;
If I change your code to the following, the function pointer addresses will be displayed correctly:
void Function1() {
}
int main() {
void*a = (void*)&Function1;
cout<<a<<endl;
cout<< (void*)&Function1<<endl;
cout<< (void*)&main<<endl;
return 0;
}
Output:
0x8048710
0x8048710
0x8048570
See the working sample here please.
The problem is, there's a standard operator overload available for
ostream& operator<<(ostream&,void*)
but not for function pointers
ostream& operator<<(ostream&,void (Function1Type*)())
and the least valid conversion draws
ostream& operator<<(ostream&,bool)
where everything other than 0x00000000 is true.
Related
I tried the following code of C++. However, the outputs of printf and std::cout are different. Why?
struct Foo
{
int a;
int b;
int c;
};
int main()
{
printf("%d\n", &Foo::c); // The output is 8
std::cout << &Foo::c << "\n"; // The output is 1
}
printf("%d\n", &Foo::c): this is undefined behavior, as &Foo::c is not an integer, but a pointer to member (but, actually, it is usual that the compiler stores pointer to data member as offset, and as 8 is the offset of Foo::c, 8 is printed).
std::cout << &Foo::c: this prints the value &Foo::c. As iostream doesn't have a pointer to member printer, it chooses the closest one: it converts it to bool, and prints it as integer. As &Foo::c converted to bool is true, 1 is printed.
The output is different because the behavior of your printf is undefined.
A pointer to member (like the one produced from &Foo::c) is not an integer. The printf function expects an integer, since you told it too with the %d specifier.
You can amend it by adding a cast to bool, like this:
printf("%d\n", (bool)&Foo::c)
A pointer to member may be converted to a bool (which you do with the cast), and the bool then undergoes integral promotion to an int on account of being an integral variadic argument to a variadic function.
Speaking of the conversion to bool, it's exactly the conversion that is applied implicitly by attempting to call std::ostream's operator<<. Since there isn't an overload of the operator that supports pointers to members, overload resolution selects another that is callable after implicitly converting &Foo::c to a boolean.
In addition to the more literal answer about why the compiler interpreted your code the way it did: you seem to have an XY problem You’re trying to format a pointer-to-member as an integer, which strongly suggests you meant to do something different.
If what you wanted was an int value stored in .c, you either need to create an instance Foo some_foo; and take some_foo.c, or else you need to declare Foo::c a static member, so there’s one unambiguous Foo::c across the entire class. Do not take the address in this case.
If what you wanted was to take an address of the .c member of some Foo, you should do as above so that Foo::c is static and refers to one specific variable, or else declare an instance and take its .c member, then take the address. The correct printf() specifier for an object pointer is %p, and to print an object pointer representation with <iostream>, convert it to void*:
printf( "%p\n", &some_foo.c );
std::cout << static_cast<void*>{&some_foo.c} << '\n';
If what you want is the offset of Foo::c within class Foo, you want the offsetof() macro in <stddef.h>. Since its return value is size_t, which is not the same size as int on 64-bit platforms, you would want to either cast the result explicitly or pass printf() the z type specifier:
#include <stddef.h>
/* ... */
constexpr size_t offset_c = offsetof( Foo, c );
printf( "%zu\n", offset_c );
cout << offset_c << '\n';
Whatever you were trying to do, if your compiler didn’t warn you about the type mismatch, you ought to turn on more warnings. This is especially true for someone coding by trial and error until the program compiles.
Function pointers of dissimilar types can't be directly compared :
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
// Doesn't compile, the comparison is not allowed
std::cout << std::boolalpha << (&foo == &bar) << std::endl;
return 0;
}
However, if one function pointer is cast to the type of the other function pointer, is it defined behavior to compare the result of that cast with the other function pointer?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
auto cast_ptr = reinterpret_cast<decltype(&bar)>(&foo);
// Printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_ptr == &bar) << std::endl;
}
How about if both operators have been cast to a common but different type?
#include <iomanip>
#include <iostream>
int foo() { return 0; }
void bar(int) {}
int main()
{
using cast_type = void(*)();
auto cast_foo = reinterpret_cast<cast_type>(&foo);
auto cast_bar = reinterpret_cast<cast_type>(&bar);
// Also printed "false" when I tried it, but is this guaranteed?
std::cout << std::boolalpha << (cast_foo == cast_bar) << std::endl;
}
I understand that function pointers compare equal if and only if they both point to nullptr or to the same function. What's not clear to me is rather or not using a function pointer that's been cast to another function pointer type in a comparison is allowed.
Context
I'm maintaining a c++ library with a c compatible API. The library logs every call made to API functions. It's become useful to selectively disable this logging for certain functions at run time. The best current proposal in terms of usability is to supply a new API function which takes as an argument a pointer to the API function whose logging should be suppressed. Since the API functions have different arguments, these pointers would have different types and would need to be cast to a common function pointer type such as void(*)(). Then, before logging an API function call, a container of void(*)() would be searched for the address of the called function to know rather or not to log that call.
From [expr.reinterpret.cast]
A function pointer can be explicitly converted to a function pointer of a different type. [...] Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.
It is unspecified whether casted function pointers compare equally.
A pointer can be explicitly converted to any integral type large enough to hold it. The mapping function is implementation-defined.
Hence it is a natural choice to convert to std::intptr_t or some other suitable type, provided the implementation doesn't use some wacky conversion.
From GCC's documentation
A cast from pointer to integer discards most-significant bits if the pointer representation is larger than the integer type, sign-extends1 if the pointer representation is smaller than the integer type, otherwise the bits are unchanged.
AKA the sane conversion. Which is probably what you'll find in most cases I'd bet.
[1] Future versions of GCC may zero-extend, or use a target-defined ptr_extend pattern. Do not rely on sign extension.
I have these two test functions:
int apply_a(int (*fun)(int, int), int m, int n) {
return (*fun)(m,n);
}
int apply_b(int (*fun)(int, int), int m, int n) {
return fun(m,n);
}
they appear to return something different, so why do both of them yield the same result?
int add(int a, int b) {return a + b;}
int res_a = apply_a(add, 2, 3); // returns 5
int res_b = apply_b(add, 2, 3); // returns 5
I would've assumed that one of them would return the pointer address or the pointer itself; rather than the value stored on the pointer...
So why is it doing this?
Because C++ offers syntactic sugar when it comes to handling the address of non-member functions and using pointers to them.
One can get address of such function:
int someFunc(int);
with either:
int (* someFuncPtr)(int) = someFunc;
or:
int (* someFuncPtr)(int) = &someFunc;
There is also syntactic sugar for using such pointer, either call pointed-to function with:
(*someFuncPtr)(5);
or with simplified syntax:
someFuncPtr(5);
(*fun)(m,n) is the same as fun(m,n) due to rules in C and C++ that convert functions to pointers to functions.
In C 2011, the rule is clause 6.3.2.1 4: “A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”. In C++, the rule is clause 4.3.
Note that a function designator is not merely an identifier that names a function. It could be an identifier, or it could be another expression. For example, if foo is the name of a function, it is automatically converted to a pointer to a function by the above. Then, since foo is a pointer to the function, *foo is the function. This means you can write:
(*fun)(m,n)
The result is that fun is automatically converted to a pointer, then * evaluates to the function, then *fun is converted back to a pointer, then the function is called. You can continue this and write:
(**************fun)(m,n)
This is the same as fun(m,n). Each * produces the function again, but the compiler automatically converts it back to a pointer. You can continue this battle forever, but the compiler will always win.
In fact, these all have the same effect:
(&fun)(m,n)
( fun)(m,n)
(*fun)(m,n)
It is because you are not returning memory addresses of these values.
Calling a function with pointer does not change it's value it's still calling the function. What you can do is return a value to a variable and then get it's memory address such as:
int result = fun(m,n);
cout << "the result " << result << " pointing at " << &result << endl;
In C and C++ name of functions are also the pointers to the function code. As any pointer you can dereference them using *, which in case of function pointers mean invocation of the function when in addition to dereferencing you use also paranthesis after them, like in your apply_a case. But also valid invocation of C and C++ function is calling them simply by their name, which is apply_b case.
The following observation arose as I was following this question about char[] and char* differences.
#include <iostream>
typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
std::cout << std::is_same<decltype(x), decltype(y)>::value << '\n';
std::cout << std::is_same<ar, pr>::value << '\n';
}
int main()
{
char data[] = "data";
char *ptr = data;
f2(data,ptr);
return 0;
}
Output ( on Apple LLVM version 4.2 (clang-425.0.28) )
1
0
Why do these report as different types, but not different decltype()s ? My suspicion is they are in fact different types due to their typedef declarations, but then why are variables reported as the same type?
In C++, as in C, a parameter that's declared to be of array type is adjusted (at compile time) to be of pointer type, specifically a pointer to the array's element type.
This happens whether the array type is specified directly or via a typedef (remember that a typedef doesn't create a new type, just an alias for an existing type).
So this:
typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
// ...
}
really means:
void f2(char* x, char* y)
{
// ...
}
Another rule, also shared by C and C++, is that an expression of array type is, in most but not all contexts, implicitly converted to a pointer to the first element of the array object. Which means that if you define an array object:
char arr[10];
you can use the name of that object as an argument to a function that takes a char* parameter (which loses the bounds information).
In C, the cases where this implicit conversion doesn't happen are:
When the array expression is the operand of sizeof (sizeof arr yields the size of the array, not the size of a pointer);
When the array expression is the operand of unary & (&arr is a pointer-to-array, not a pointer-to-pointer); and
When the array expression is a string literal used to initialize an object of array type (char s[] = "hello"; initializes s as an array, not as a pointer).
None of these cases (or the other cases that occur in C++) appear in your program, so your call:
f2(data,ptr);
passes two pointer values of type char* to f2.
Inside f2, the parameter objects x and y are both of type char*, so std::is_same<decltype(x), decltype(y)>::value is true.
But the types ar and pr are distinct. ar is an incomplete array type char[], and pr is the pointer type char*.
Which explains your program's output. The weirdness happens because the parameter x, which you defined with the array type ar, is really of type char*, which is the same type as pr.
The C family is pass-by-value, and the C value of an array is a pointer to its first element. When you pass an item declared to be an array to a function, what's really getting passed is that pointer, and C treats the prototype as if you declared it that way.
I changed the code so that we could see how calling a f2 changes the type. Before the call the variables are of different type. After the call they have become same
typedef char ar[];
typedef char* pr;
void f2(ar x, pr y)
{
cout << is_same<decltype(x), decltype(y)>::value << '\n'; //same type
}
int main()
{
ar data = "data";
pr ptr = data;
cout << is_same<decltype(data), decltype(ptr)>::value << '\n'; // different
f2(data,ptr);
return 0;
}
the output is
0
0
.As #jthill, #Dyp and #keith Thompson says this is because of decaying of the array to pointer.
I am a C guy and I'm trying to understand some C++ code. I have the following function declaration:
int foo(const string &myname) {
cout << "called foo for: " << myname << endl;
return 0;
}
How does the function signature differ from the equivalent C:
int foo(const char *myname)
Is there a difference between using string *myname vs string &myname? What is the difference between & in C++ and * in C to indicate pointers?
Similarly:
const string &GetMethodName() { ... }
What is the & doing here? Is there some website that explains how & is used differently in C vs C++?
The "&" denotes a reference instead of a pointer to an object (In your case a constant reference).
The advantage of having a function such as
foo(string const& myname)
over
foo(string const* myname)
is that in the former case you are guaranteed that myname is non-null, since C++ does not allow NULL references. Since you are passing by reference, the object is not copied, just like if you were passing a pointer.
Your second example:
const string &GetMethodName() { ... }
Would allow you to return a constant reference to, for example, a member variable. This is useful if you do not wish a copy to be returned, and again be guaranteed that the value returned is non-null. As an example, the following allows you direct, read-only access:
class A
{
public:
int bar() const {return someValue;}
//Big, expensive to copy class
}
class B
{
public:
A const& getA() { return mA;}
private:
A mA;
}
void someFunction()
{
B b = B();
//Access A, ability to call const functions on A
//No need to check for null, since reference is guaranteed to be valid.
int value = b.getA().bar();
}
You have to of course be careful to not return invalid references.
Compilers will happily compile the following (depending on your warning level and how you treat warnings)
int const& foo()
{
int a;
//This is very bad, returning reference to something on the stack. This will
//crash at runtime.
return a;
}
Basically, it is your responsibility to ensure that whatever you are returning a reference to is actually valid.
Here, & is not used as an operator. As part of function or variable declarations, & denotes a reference. The C++ FAQ Lite has a pretty nifty chapter on references.
string * and string& differ in a couple of ways. First of all, the pointer points to the address location of the data. The reference points to the data. If you had the following function:
int foo(string *param1);
You would have to check in the function declaration to make sure that param1 pointed to a valid location. Comparatively:
int foo(string ¶m1);
Here, it is the caller's responsibility to make sure the pointed to data is valid. You can't pass a "NULL" value, for example, int he second function above.
With regards to your second question, about the method return values being a reference, consider the following three functions:
string &foo();
string *foo();
string foo();
In the first case, you would be returning a reference to the data. If your function declaration looked like this:
string &foo()
{
string localString = "Hello!";
return localString;
}
You would probably get some compiler errors, since you are returning a reference to a string that was initialized in the stack for that function. On the function return, that data location is no longer valid. Typically, you would want to return a reference to a class member or something like that.
The second function above returns a pointer in actual memory, so it would stay the same. You would have to check for NULL-pointers, though.
Finally, in the third case, the data returned would be copied into the return value for the caller. So if your function was like this:
string foo()
{
string localString = "Hello!";
return localString;
}
You'd be okay, since the string "Hello" would be copied into the return value for that function, accessible in the caller's memory space.
Your function declares a constant reference to a string:
int foo(const string &myname) {
cout << "called foo for: " << myname << endl;
return 0;
}
A reference has some special properties, which make it a safer alternative to pointers in many ways:
it can never be NULL
it must always be initialised
it cannot be changed to refer to a different variable once set
it can be used in exactly the same way as the variable to which it refers (which means you do not need to deference it like a pointer)
How does the function signature differ from the equivalent C:
int foo(const char *myname)
There are several differences, since the first refers directly to an object, while const char* must be dereferenced to point to the data.
Is there a difference between using string *myname vs string &myname?
The main difference when dealing with parameters is that you do not need to dereference &myname. A simpler example is:
int add_ptr(int *x, int* y)
{
return *x + *y;
}
int add_ref(int &x, int &y)
{
return x + y;
}
which do exactly the same thing. The only difference in this case is that you do not need to dereference x and y as they refer directly to the variables passed in.
const string &GetMethodName() { ... }
What is the & doing here? Is there some website that explains how & is used differently in C vs C++?
This returns a constant reference to a string. So the caller gets to access the returned variable directly, but only in a read-only sense. This is sometimes used to return string data members without allocating extra memory.
There are some subtleties with references - have a look at the C++ FAQ on References for some more details.
#include<iostream>
using namespace std;
int add(int &number);
int main ()
{
int number;
int result;
number=5;
cout << "The value of the variable number before calling the function : " << number << endl;
result=add(&number);
cout << "The value of the variable number after the function is returned : " << number << endl;
cout << "The value of result : " << result << endl;
return(0);
}
int add(int &p)
{
*p=*p+100;
return(*p);
}
This is invalid code on several counts. Running it through g++ gives:
crap.cpp: In function ‘int main()’:
crap.cpp:11: error: invalid initialization of non-const reference of type ‘int&’ from a temporary of type ‘int*’
crap.cpp:3: error: in passing argument 1 of ‘int add(int&)’
crap.cpp: In function ‘int add(int&)’:
crap.cpp:19: error: invalid type argument of ‘unary *’
crap.cpp:19: error: invalid type argument of ‘unary *’
crap.cpp:20: error: invalid type argument of ‘unary *’
A valid version of the code reads:
#include<iostream>
using namespace std;
int add(int &number);
int main ()
{
int number;
int result;
number=5;
cout << "The value of the variable number before calling the function : " << number << endl;
result=add(number);
cout << "The value of the variable number after the function is returned : " << number << endl;
cout << "The value of result : " << result << endl;
return(0);
}
int add(int &p)
{
p=p+100;
return p;
}
What is happening here is that you are passing a variable "as is" to your function. This is roughly equivalent to:
int add(int *p)
{
*p=*p+100;
return *p;
}
However, passing a reference to a function ensures that you cannot do things like pointer arithmetic with the reference. For example:
int add(int &p)
{
*p=*p+100;
return p;
}
is invalid.
If you must use a pointer to a reference, that has to be done explicitly:
int add(int &p)
{
int* i = &p;
i=i+100L;
return *i;
}
Which on a test run gives (as expected) junk output:
The value of the variable number before calling the function : 5
The value of the variable number after the function is returned : 5
The value of result : 1399090792
One way to look at the & (reference) operator in c++ is that is merely a syntactic sugar to a pointer. For example, the following are roughly equivalent:
void foo(int &x)
{
x = x + 1;
}
void foo(int *x)
{
*x = *x + 1;
}
The more useful is when you're dealing with a class, so that your methods turn from x->bar() to x.bar().
The reason I said roughly is that using references imposes additional compile-time restrictions on what you can do with the reference, in order to protect you from some of the problems caused when dealing with pointers. For instance, you can't accidentally change the pointer, or use the pointer in any way other than to reference the singular object you've been passed.
In this context & is causing the function to take stringname by reference.
The difference between references and pointers is:
When you take a reference to a variable, that reference is the variable you referenced. You don't need to dereference it or anything, working with the reference is sematically equal to working with the referenced variable itself.
NULL is not a valid value to a reference and will result in a compiler error. So generally, if you want to use an output parameter (or a pointer/reference in general) in a C++ function, and passing a null value to that parameter should be allowed, then use a pointer (or smart pointer, preferably). If passing a null value makes no sense for that function, use a reference.
You cannot 're-seat' a reference. While the value of a pointer can be changed to point at something else, a reference has no similar functionality. Once you take a variable by reference, you are effectively dealing with that variable directly. Just like you can't change the value of a by writing b = 4;. A reference's value is the value of whatever it referenced.