Printing a pointer-to-member-field - c++

I was debugging some code involving pointers to member fields, and i decided to print them out to see their values. I had a function returning a pointer to member:
#include <stdio.h>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
I tried using cout:
#include <iostream>
int main()
{
std::cout << select(0) << " and " << select(3) << '\n';
}
I got 1 and 0. I thought the numbers indicated the position of the field inside the struct (that is, 1 is y and 0 is x), but no, the printed value is actually 1 for non-null pointer and 0 for null pointer. I guess this is a standard-compliant behavior (even though it's not helpful) - am i right? In addition, is it possible for a compliant c++ implementation to print always 0 for pointers-to-members? Or even an empty string?
And, finally, how can i print a pointer-to-member in a meaningful manner? I came up with two ugly ways:
printf("%d and %d\n", select(0), select(3)); // not 64-bit-compatible, i guess?
ptr_to_member temp1 = select(0); // have to declare temporary variables
ptr_to_member temp2 = select(3);
std::cout << *(int*)&temp1 << " and " << *(int*)&temp2 << '\n'; // UGLY!
Any better ways?

Pointers to members are not as simple as you may think. Their size changes from compiler to compiler and from class to class depending on whether the class has virtual methods or not and whether it has multiple inheritance or not. Assuming they are int sized is not the right way to go. What you can do is print them in hexadecimal:
void dumpByte(char i_byte)
{
std::cout << std::hex << static_cast<int>((i_byte & 0xf0) >> 4);
std::cout << std::hex << static_cast<int>(i_byte & 0x0f));
} // ()
template <typename T>
void dumpStuff(T* i_pStuff)
{
const char* pStuff = reinterpret_cast<const char*>(i_pStuff);
size_t size = sizeof(T);
while (size)
{
dumpByte(*pStuff);
++pStuff;
--size;
} // while
} // ()
However, I'm not sure how useful that information will be to you since you don't know what is the structure of the pointers and what each byte (or several bytes) mean.

Member pointers aren't ordinary pointers. The overloads you expect for << aren't in fact there.
If you don't mind some type punning, you can hack something up to print the actual values:
int main()
{
ptr_to_member a = select(0), b = select(1);
std::cout << *reinterpret_cast<uint32_t*>(&a) << " and "
<< *reinterpret_cast<uint32_t*>(&b) << " and "
<< sizeof(ptr_to_member) << '\n';
}

You can display the raw values of these pointer-to-members as follows:
#include <iostream>
struct test {int x, y, z;};
typedef int test::*ptr_to_member;
ptr_to_member select(int what)
{
switch (what) {
case 0: return &test::x;
case 1: return &test::y;
case 2: return &test::z;
default: return NULL;
}
}
int main()
{
ptr_to_member x = select(0) ;
ptr_to_member y = select(1) ;
ptr_to_member z = select(2) ;
std::cout << *(void**)&x << ", " << *(void**)&y << ", " << *(void**)&z << std::endl ;
}
You get warnings about breaking strict anti-aliasing rules (see this link), but the result is what you might expect:
0, 0x4, 0x8
Nevertheless, the compiler is free to implement pointer-to-member functionality however it likes, so you can't rely on these values being meaningful.

I think you should use printf to solve this problen
#include <stdio.h>
struct test{int x,y,z;}
int main(int argc, char* argv[])
{
printf("&test::x=%p\n", &test::x);
printf("&test::y=%p\n", &test::y);
printf("&test::z=%p\n", &test::z);
return 0;
}

Related

Alternatives to std::array for objects of different types in C++11

I am looking for better solutions on how to organize and access my data.
My data is a set of structures (_array_10 and _array_20 in the example below) that contain std::array of different sizes (see my_data below).
Ideally, I would like to access it as it was an array of structs with different lengths, but this is not allowed, since different lengths are different types.
The solution I have below works, but I find it extremely ugly (specially the array of void *).
Q1. Any ideas on how to have a safer, more efficient/portable, or at least less ugly solution?
Q2. Is the proposed solution without templates portable? It relies on the fact that the length is stored before the rest of the data, since casting the pointer to an object with wrong length would mess the access to all fields that come after the first field of variable length.
My limitations include:
C++11
standard libraries
no std::vector
memory usage prevents me from being able to simply allocate an array of my_data with the maximum possible length
the bulk of the data (_array_10, _array_20, etc) will be placed in a memory area reserved specially for it
Using data_view and template require knowledge of the length of the arrays in build time. It would be great if we could avoid it.
Question edited to include the solution proposed by Guillaume Racicot
#include <iostream>
#include <array>
std::array<void *, 2> _ptrs;
template <int length>
struct my_data
{
int array_length;
std::array<int, length> something;
std::array<int, length> data;
my_data()
{
array_length = length;
}
};
struct my_data_view
{
int array_length;
const int * something;
const int * data;
template <int length>
my_data_view(my_data<length> const & data_in) :
array_length(length),
something(data_in.something.data()),
data(data_in.data.data())
{}
};
template <int length>
void
print_element(int array_idx, int element)
{
my_data<length> * ptr = reinterpret_cast<my_data<length> *>(_ptrs[array_idx]);
std::cout << "array " << length << ", data[" << element << "] = " << ptr->data[element] << ".\n";
}
void
print_element(int array_idx, int element)
{
my_data<1> * ptr = reinterpret_cast<my_data<1> *>(_ptrs[array_idx]);
int length = ptr->array_length;
int data_to_print = 0;
switch (length)
{
case 10:
{
data_to_print = reinterpret_cast<my_data<10> *>(_ptrs[array_idx])->data[element];
break;
}
case 20:
{
data_to_print = reinterpret_cast<my_data<20> *>(_ptrs[array_idx])->data[element];
break;
}
}
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
void
print_element(my_data_view view, int element)
{
int length = view.array_length;
int data_to_print = view.data[element];
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
int
main()
{
my_data<10> _array_10;
my_data<20> _array_20;
_ptrs[0] = static_cast<void *>(&_array_10);
_ptrs[1] = static_cast<void *>(&_array_20);
_array_10.data[5] = 11;
_array_20.data[5] = 22;
std::cout << "using template\n";
print_element<10>(0, 5);
print_element<20>(1, 5);
std::cout << "\nwithout template\n";
print_element(0, 5);
print_element(1, 5);
std::cout << "\nusing data_view\n";
print_element(my_data_view(_array_10), 5);
print_element(my_data_view(_array_20), 5);
}
You could create a dynamic view class that don't allocate:
struct my_data_view
{
int array_length;
std::span<int> something;
std::span<int> data;
template<int length>
my_data_view(my_data<length> const& data) :
array_length{length}, something{data.something}, data{data.data}
{}
};
Spans simply are a pointer and a size. If you don't have access to std::span (which is from C++20) you can simply replace those member with int* and use array_length for the size.
This my_data_view type is used like that:
void
print_element(my_data_view view, int element)
{
int length = view.array_length;
int data_to_print = view.data[element];
std::cout << "array " << length << ", data[" << element << "] = " << data_to_print << ".\n";
}
This is the code that will work both with std::span and simple int*.

Can any primitive type be passed into a function expecting a pointer?

Basically I'm wondering what the rules are for passing in pointers vs references to functions in C++. I couldn't find them stated anywhere. Can you pass a primitive type integer, for example, into a function expecting a pointer? Can't you only pass in pointers to methods expecting pointers?
A pointer is just a memory address and in c++ you can get the address of a variable by using the &. Here is an example
#include <iostream>
void increment(int& x)
{
++x;
}
void increment2(int* x)
{
++(*x);
}
int main()
{
int i = 1;
int * p = new int(1);
increment2(&i);
increment2(p);
std::cout << i << std::endl;
std::cout << *p << std::endl;
increment(i);
increment(*p);
std::cout << i << std::endl;
std::cout << *p << std::endl;
}
output
2
2
3
3
try it:
https://godbolt.org/z/br9APq

Problem with overloaded typecast operator for struct within a union

I'm trying to implement a simple vector-swizzling functionality as a pet project to get into template metaprogramming. With the help of open-source mathematics library glm and some other posts on SO, I have come up with a solution which is basically working but has one error.
I have implemenented several structs which hold the data I need to represent a two dimensional eucledian vector. The struct "vec2" has a union which holds a float array with two elements (float data[2]) and two instances of struct "scalarSwizzle" which is supposed to implement the swizzling mechanic which allows me to acces the vector like so vec.data[0] or so vec.x.
Following the code I implemented so far:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
template<typename T>
struct vec2
{
union
{
T data[2];
scalarSwiz<T, 0> x;
scalarSwiz<T, 1> y;
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}
The output is the following:
value vec1.data[0]: 5
value vec1.data[1]: 567.4
value vec1.x: 5
value vec1.y: 567.4
print func: 5
print func: 567.4
print func: 5
print func: 2.5565e-39
I expected the output to be the same for both printing the values directly in main() and via print() but vec.y is not resolved when I print it via the print() function. So I guess something is wrong with the overloaded typecast operator in "scalarSwizzle" but i have no idea what.
What I also dont understand is, why visual studio also doesn't resolve the value properly as seen on the following image:
vec1.y seem to be pointing to the same physical address then vec.x, while the direct std::cout in main() works fine.
I've been trying for a couple of days now to wrap my head around the problem, why the overloaded typecast operator doesnt work for vec.y but i just dont get it. Maybe someone here can help my with this problem.
Thank you!
First of all
template<typename T, unsigned int I>
struct scalarSwiz
{
T value[1];
T &operator=(const T newValue)
{
value[I] = newValue;
return value[I];
}
operator T()
{
return value[I];
}
};
results in undefined behavior if I != 0 (array access out of bounds) so don't expect your code to be correct or even stable.
Secondly, accessing an inactive member of a union is also undefined behavior (as per c++ standard). However, msvc, gcc and clang extend the c++ standard so that accessing inactive member behaves like we expect it to.
And finally, your scalarSwiz type can be replaced by an anonymous struct:
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
In regards to your Visual Studio debugger display: this is because of your scalarSwiz definition. You define an array of length 1 T value[1] and you put 2 scalarSwiz objects in a union. Because every member of a union share the same memory (or rather start at the same memory location), both of your value members point to the beginning of the data array. The watch window only displays the members and their values of a certain type, it has no knowledge of your quirky indexing. And because both arrays occupie the same memory, the same value is shown.
I updated my code regarding Timo's answer:
#include <iostream>
template<typename T>
void print(T value)
{
std::cout << "print func: " << value << std::endl;
}
template<typename T>
struct vec2
{
union
{
T data[2];
struct
{
T x, y;
};
};
vec2()
{
x = 0.0f;
y = 1.0f;
}
vec2(T pA, T pB)
{
x = pA;
y = pB;
}
};
int main(int argc, char *args[])
{
vec2<float> vec1{5.0f, 1.0f};
std::cout << "value vec1.data[0]: " << vec1.data[0] << std::endl;
std::cout << "value vec1.data[1]: " << vec1.data[1] << std::endl;
std::cout << "value vec1.x: " << vec1.x << std::endl;
std::cout << "value vec1.y: " << vec1.y << std::endl << std::endl;
print(vec1.data[0]);
print(vec1.data[1]);
print(vec1.x);
print(vec1.y);
std::cin.get();
}

Dev c++ 5.11 on Windows 8 Produces wrong answer

#include<iostream>
#include<conio.h>
class Number
{
private:
int x, y;
public:
Number()
{
x = y = 100;
}
void avg()
{
std::cout<<"x = "<<std::cout<<x;
std::cout<<std::endl;
std::cout<<"Y = "<<std::cout<<y;
std::cout<<std::endl;
std::cout<<"Average = "<<std::cout<<(x+y)/2;
}
};
main()
{
Number n;
n.avg();
}
This programme runs but shows wrong answer, may be showing addresses of memory locations instead of showing the assigned values of 100. Please correct me why it is behaving like this?
std::cout << "x = " << std::cout << x;
is wrong. You need
std::cout << "x = " << x;
Otherwise, the std::cout stream object in ...<< std::cout is implicitly converted to a (void*) when invoking operator<< on it, and therefore the pointer (an address) is displayed.
The conversion to void* exists for historic reasons (the safe bool idiom), but in C++11 was removed, due to the introduction of explicit conversion operators, so your code should not compile in C++11.

Dereferencing pointers to members of union

The following code prints '2' four times. Why does it never print '1'? Can someone explain me exactly what is happening here?
#include <iostream>
int main () {
union IntegersUnion {
int a;
int b;
};
IntegersUnion q;
q.a = 1;
q.b = 2;
std::cout << "(*(&q.a)) = " << (*(&q.a)) << std::endl;
std::cout << "(*(&q.b)) = " << (*(&q.b)) << std::endl;
std::cout << "(*(&(q.a))) = " << (*(&(q.a))) << std::endl;
std::cout << "(*(&(q.b))) = " << (*(&(q.b))) << std::endl;
return 0;
}
A union shares the memory between its members. By doing:
q.a = 1;
q.b = 2;
the second assignment overwrites the a.
union uses the same memory for all of its members.
So, when you assign q.b = 2;, q.a will be 2, too.
Every item in the union refers to the same location.
The most common use of union is something like this:
struct {
int dataTypeID;
union {
char char_here;
int number_here;
}
} incoming_data;
In this example, incoming_data is data imported from a file, where dataTypeID tells you what kind of data it is. (There are many file formats which optimize space in this fashion.)