Is printing of a member pointer to an int defined - c++

Suppose I have this code:
#include <iostream>
struct Mine
{
int a;
int b;
};
int main()
{
int Mine::* memberPointerA = &Mine::a;
int Mine::* memberPointerB = &Mine::b;
std::cout << memberPointerA;
std::cout << "\n";
std::cout << memberPointerB;
}
When I run this with Microsoft Visual C++ (2015)
I get the following output
1
1
The output I expect is something more like this:
1
2
So this begs the question: Is this printing of a member pointer defined behavior?

There's a defined conversion from pointer to bool. Since the member variable pointers are not NULL, they evaluate as true and print as 1.

The key issue at hand is that a pointer-to-member cannot be converted to void*, which is what the overload that usually handles printing pointers takes.
Thus, the next best conversion is used, which is the conversion pointer->bool. Both pointers are not null pointers, thus you get the output you see.
If you try printing "normal" pointers (as opposed to pointers to member), you would get the some output along the lines of what you expected initially.

Related

Unexpected behaviour of std::cout [duplicate]

This question already has answers here:
How to print function pointers with cout?
(7 answers)
Closed 5 years ago.
I was playing around with function pointers recently, when I discovered that the value of the function pointer as printed by std::cout always evaluates to 1.
However that was not the case with printf(), and it prints the expected result.
It'd be great if someone could explain the reason behind such behavior.
Below is the code sample for reference.
#include<iostream>
using namespace std;
int fun(int a)
{
return 0;
}
int main()
{
cout<<(&fun)<<endl; //always prints 1
printf("%u",&fun); //this prints the expected result
return 0;
}
The printf call is simply undefined behavior. A function pointer is not an unsigned integer, and thus supplying it for a %u argument is not valid. (Try running this code on a 64-bit platform. You won't get the correct function pointer value.)
The cout on the other hand is type-safe. The compiler sees a function pointer argument and tries to find the best printing function (operator<< overload) it can. There is no such overload for function pointers themselves and the pointers don't offer a lot of implicit conversions. There is just one overload that works, and that is the one for bool. So the compiler converts the non-NULL function pointer to true and passes that. The overload then prints this as 1, but you could use the std::boolalpha modifier to make it print as true instead.
Your cout treats (&fun) as a boolean expression and warns that it will always evaluate to true (i.e. non-zero).
Try casting it to void* as addresses should be printed, and check what happens:
#include <iostream>
#include <stdio.h>
using namespace std;
int fun(int a){
return 0;
}
int main(){
cout<<(void*)(&fun)<<endl; //always prints 1
/* Side note: This will print the same as above */
// cout<<(void*)(fun)<<endl; // note the missing &
printf("%p",(void*)&fun); //this prints the expected result
// while(1);
return 0;
}
output on mu machine:
0x401460
0x401460

Sorting 2D arrays with qsort - correct typecasting

I am having a problem with using c++ qsort compare function to correctly lexicographically sort 2d array of ints. I have already read many similar questions here but with no success. When making the custom compare function, its arguments are in form of
int compar (const void* p1, const void* p2)
now, I know that it the arguments are pointers to my variables, that are each ponters to one row of my array. I would like to index and compare my array in the normal conventional way using something like the following.
if(p1[0] <= p2[0]) {...}
Because I know, that the format
p1[i]
is just a shortcut for pointer arithmetic, I guess when I am recieving an argument "pointer to pointer to int", I should typecast and use it this way:
if(*(int**)p1[0] <= *(int**)p2[0]) {...}
Compiler however gives me many these errors
main.cpp:8:20: error: ‘const void*’ is not a pointer-to-object type
main.cpp:8:37: warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]
My question is, how to correctly typecast this, so it would allow me to compare my rows. Also, I would like to understand, what am I doing wrong here to avoid making these pointer related mistakes in the future.
It's because operator[] takes precedence over cast. b[0] is trying to be resolved first. So even if it's b[0] it complains you are doing pointer arithmetic on void* type. You need to cast 1st.
#include <iostream>
using namespace std;
int main() {
int a[10];
a[0] = 1337;
a[1] = 42;
void* b;
b = (void*)a;
// cout << (int*)b[0] << '\n'; // will break
cout << ((int*)b)[0] << '\n';
// dedicated c++ cast imposes more verbose syntax - i.e. you can't miss the ()
cout << static_cast<int*>(b)[1] << '\n';
return 0;
}
That being said I still would encourage to use c++ dedicated features for what you're doing =).

Why is the value of a pointer-to-member always the same for different members of the same struct?

I have the following code:
#include <iostream>
#include <string>
using namespace std;
struct foo_s {
string a;
string b;
string c;
};
void print_field(foo_s* foo, string foo_s::* field) {
cout << "field: " << field << " - " << foo->*field << endl;
}
int main() {
foo_s my_foo = {
"a",
"b",
"c",
};
print_field(&my_foo, &foo_s::a);
print_field(&my_foo, &foo_s::b);
print_field(&my_foo, &foo_s::c);
return 0;
}
Its output is:
field: 1 - a
field: 1 - b
field: 1 - c
I'm having a bit of trouble understanding the specifics of what's going on in the print_field() function. Namely:
What's the type of field? I imagine it's pointer-to-string-foo_s-member
Why is the value of field always the same (1 in this case), yet foo->*field yields different results?
Mainly, I'm baffled at #2. I imagined field would be an "offset" from the start of the struct and foo->*field would have been conceptually equivalent to something like
char* ptr = static_cast<char*>(foo);
ptrdiff_t offset = somehow_get_the_byte_offset_from_pointer_to_member(field);
ptr = ptr[offset];
string result = *static_cast<string*>(ptr);
but that seems to be out since field's value doesn't vary across calls. What am I missing? How exactly is this specific operation described by the standard?
There's no overload for << to format the value of a member pointer, so you won't get anything particularly useful if you try. There is an overload for bool, and member pointers are convertible to bool, so that is what happens here. The pointer isn't null, so it converts to true, which by default is formatted as 1.
To demonstrate further, you could try streaming boolalpha first; then you should see true rather than 1.
The type of field is, as you say, a pointer to a member of foo_s of type std::string.
The value of field is 1 in all of these cases, because pointers to member are convertible to bool, so when you output them, you get a 1 because they are not null.

const char* to int cast?

I suppose the behaviour of the following snippet is supposed to be undefined but I just wanted to make sure I am understanding things right.
Let's say we have this code:
#include <iostream>
int main()
{
std::cout << "mamut" - 8 << std::endl;
return 0;
}
So what I think this does is (char*)((int)(const char*) - (int)), though the output after this is pretty strange, not that I expect it to make any real sense. So my question is about the casting between char* and int - is it undefined, or is there some logic behind it?
EDIT:
Let me just add this:
#include <iostream>
int main ()
{
const char* a = "mamut";
int b = int(a);
std::cout << b << std::endl;
std::cout << &a <<std::endl;
// seems b!= &a
for( int i = 0; i<100;i++)
{
std::cout<<(const char*)((int)a - i)<<std::endl;
}
return 0;
}
The output after i gets big enough gives me a something like _Jv_RegisterClasses etc.
Just for the record:
std::cout << a - i << std::endl;
produces the same result as:
std::cout<<(const char*)((int)a - i)<<std::endl;
There is no cast, you are merely telling cout that you want to print the string at the address of the string literal "mamut" minus 8 bytes. You are doing pointer arithmetic. cout will then print whatever happens to be at that address, or possibly crash & burn, since accessing arrays out of bounds leads to undefined behavior.
EDIT
Regarding the edit by the op: converting an address to int doesn't necessarily result in a correct number identical to the address. An address doesn't necessarily fit in an int and on top of that, int is a signed type and it doesn't make any sense to store addresses in signed types.
To guarantee a conversion from pointer to integer without losses, you need to use uintptr_t from stdint.h.
To quote the C standard 6.3.2.3 (I believe C++ is identical in this case):
Any pointer type may be converted to an integer type. Except as
previously specified, the result is implementation-defined. If the
result cannot be represented in the integer type, the behavior is
undefined. The result need not be in the range of values of any
integer type.
There is no casting going on. "mamut" is a pointer to characters, and - 8 will do pointer arithmetic on it. You are right that it's undefined behavior, so even though the semantic behavior is pointer arithmetic, the runtime behavior can be literally anything.
You are printing string starting from address of "mamut" minus 8 bytes till null terminator i.e. in total 8+5 = 13 chars

Why is the size of an array inconsisten depending on its location in the source code?

I can declare animal_array1 and animal_array2. First one on the stack, while the second one is ... well, still on the stack but this time declared as a function parameter. Here is a sample code:
#include <iostream>
using namespace std;
struct Animal
{
};
void test(Animal animal_array2[10])
{
Animal animal_array1[10];
if(sizeof(animal_array2) == sizeof(animal_array1))
cout << "Both sizes are equal. That's expected!" << endl;
else
cout << "Mhhh sizes are *NOT* equal. That wasn't expected at all!" << endl;
}
int main()
{
Animal unused_var[10];
test(unused_var);
}
The output is:
$./a.out
Mhhh sizes are *NOT* equal. That wasn't expected at all!
How can it be? Gcc bug? Or is it standard behavior? How can we get such streched results from the same apparent type?
Arrays are the only data types in C and C++ that cannot be passed by value. So an array decays to a pointer to the first element of the array (when declared and passed) as a function parameter.
So basically this:
void test(Animal animal_array2[10])
is actually:
void test(Animal *animal_array2)
but only as function parameter
and the array passed as a parameter:
test(unused_var);
decays to a pointer to the first elem in the array:
test(&(unused_var[0]));
(as a sidenote: but without the actual dereferencing)
Arrays will decay into pointers when passed to a function in C++. Typically what you do is pass the known size to the function, as a separate parameter. Not in the between the square brackets.