Is it legal c++ to use reference as array/pointer? - c++

My team (including myself) is new to C++. A piece of our new development is a C++ function that needs to interface with a C function that takes an array as input. Something like the following construct was made to achieve this:
#include "stdio.h"
void the_c_function(double *array, int len)
{
for (int i = 0; i < len; i++)
{
printf("%d: %g\n", i, array[i]);
}
}
void the_cpp_wrapper(double& dref, int len)
{
the_c_function(&dref, len);
}
int main()
{
const int LEN = 4;
double dbl_array[LEN] = { 3,4,5,6 };
the_cpp_wrapper(dbl_array[0], LEN);
return 0;
}
When compiled, this works as expected: it prints the contents of the array:
0: 3
1: 4
2: 5
3: 6
But this feels hardly legal to me or at the best something that should be discouraged.
Is this legal C++, i.e. is it guaranteed that a pointer to a reference of an array points to the original array?
Is there any reason why one would do it like this instead of using a pointer directly instead of using the reference as inbetween?

My team (including myself) is new to C++. ...
[...]
... something that should be discouraged.
You should get in the habit now of using the Standard C++ Library, in your case the best choice is std::vector:
#include <stdio.h>
#include <stdlib>
#include <vector>
void the_c_function(const double *array, size_t len) {/*...*/}
void the_cpp_wrapper(const std::vector<double>& v)
{
the_c_function(v.data(), v.size());
}
// ----------------------------
int main()
{
const std::vector<double> dbl_array { 3,4,5,6 };
the_cpp_wrapper(dbl_array);
return EXIT_SUCCESS;
}
You also should be clearer about const double* vs. double*, C++ intentionally wants you to use a much more verbose const_cast<double*> to cast-away const-ness.
If you want to go "all in" with C++, you can make the_cpp_wrapper() a bit more generic with a template:
template<typename TSpan>
void the_cpp_wrapper(const TSpan& v)
{
the_c_function(v.data(), v.size());
}
With this code, you can pass anything to the_cpp_wrapper that has data() and size() methods. (Note that TSpan "can" be std::span<int> which could cause some obscure compiler errors; there are ways to fix that, but it's more C++.)
Not directly related, but you'll probably find std::span useful too.

The question of code readability aside,
is it guaranteed that a pointer to a reference of an array points to the original array?
Yes, see § 5.5 Expressions:
If an expression initially has the type “reference to T” ([dcl.ref], [dcl.init.ref]), the type is adjusted to T prior to any further analysis. The expression designates the object or function denoted by the reference, and the expression is an lvalue or an xvalue, depending on the expression.
And §8.3.2 References:
4   It is unspecified whether or not a reference requires storage.
5   There shall be no references to references, no arrays of references, and no pointers to references.
In other words, an "address of a reference" isn't a thing; given double& dref, taking an address &dref will give the address of the original element inside the array.

Yes it is legal and it is guaranteed to reference to the original element in the array based on your code.
Some people like to design interface to force the caller to pass by reference to avoid checking whether the argument is a null pointer, which might be required when passing by pointer.

Related

Convert function reference to char* and back

I need to store a function reference as a char*, and later call that function with only the char*.
I am looking for something like:
char* funcRef = (char*)myFunc;
//...
(void (*funcRef)())();
How do you do this? (Note: I am not asking how to call a function by reference, just if its possible to store a reference to it as a char* and then convert it back)
This conversion is not allowed. The allowable conversions are given in section 6.3 Conversions, sub-subsection 6.3.2.3 Pointers, of which paragraphs (6) and (8) apply to function pointers.
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined...
and
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
Conversion between pointer to function and pointer to object is not on the allowed list; it is therefore disallowed.
There are systems where pointers to functions and pointers to objects are not interchangeable. The most obvious case is where the size of a function pointer is not the same as the size of an object pointer, such as Harvard architecture, or the 8086 in Compact or Medium model.
The reason your code isn't working is because a char* pointer is not a function pointer. You cannot call a char* as if it was a function. You need to cast that pointer back to a function pointer prior to using it as a function pointer.
Note very well: Whether this will work at all is highly compiler and system dependent.
There is nothing in the C standard that says anything about converting a pointer to a function to a pointer to an object, or vice versa. This is undefined behavior. On the other hand, POSIX standard requires that a compliant implementation must be able to convert a pointer to void to a pointer to a function. (Note: The reverse capability is not required.)
This question is also tagged as C++. Prior to C++11, converting a pointer to a function to a pointer to an object, or vice versa, was illegal. The compiler had to issue a diagnostic message. On POSIX-compliant systems, the compiler would issue a diagnostic and then generate the POSIXly-compliant object code. In C++11 and later, converting converting between pointers to functions to a pointers to an object, or vice versa, is conditionally-supported.
With those caveats, the following works on my POSIX-compliant machine, with multiple compilers. Whether it works on a non-POSIX compliant machine with non-POSIX complaint compilers is anyone's guess.
C++ version:
#include <iostream>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
using Fptr = int(*)(int);
Fptr fun = reinterpret_cast<Fptr>(vptr);
std::cout << fun(k) << '\n';
}
int main ()
{
call_callback(reinterpret_cast<void*>(sqr), 2);
call_callback(reinterpret_cast<void*>(p42), 2);
}
C version:
#include <stdio.h>
int sqr (int k) { return k*k; }
int p42 (int k) { return k+42; }
void call_callback(void* vptr, int k)
{
printf ("%d\n", ((int(*)(int))(vptr))(k));
}
int main ()
{
call_callback((void*)(sqr), 2);
call_callback((void*)(p42), 2);
}

C++ rvalue and pointer of pointer when should I use it?

Please consider these 2 lines of code
void doStuff(int ** i)
void doStuff2( int && i)
in the first one I assume that it is a pointer of pointer and the second is an rvalue,
I came across this question and it explains the rvalue but when should I use the first and when should I use the second ?
could you clarify this to me please ?
int ** i is a pointer to a pointer.
Generally, use this sparingly, as this may have different meanings and you have better ways to express that in C++.
It may be a pointer to single variable containing a pointer to a single int:
int value = 0;
int * pValue = &value;
int ** ppValue = &pValue;
However, each may also be a pointer to the first element of an array:
int valuesA[1000], valuesB[100], valuesC[10];
int * pValues[] = { valuesA, valuesB, valuesC };
// these are actually pointers to the first element of the array
int ** ppValues = pValues;
Use this only with clear documentation how to access elements, how to know the element sizes, and who is responsible for freeing (if any), how long the pointers are valid etc.
Usually, if you have such an array / matrix, you certainly should wrap it behind a safe-to-use interface, or replace it alltogether e.g. with a vector<vector<int>>.
Even for the single-int use cases there are usually better options. E.g. a function signature that allows to modify a pointer, a reference to a pointer would be more suitable:
bool SelectValue(int *& p) { ... }
int && is a rvalue reference.
Unlike the int **, this is not a double indirection.
It is, roughly a reference that can also bind to a temporary value.
("Normal" references cannot).
A Brief Introduction to Rvalue References

Technicalities involved with array of references

I wrote this code for the following problem. My compiler is givin me the following error- [Error] declaration of 'a' as array of references. What is the problem?
void repfunc(int& a[],int size){
for(int i=size-1;i>=0;--i){
if(a[i]==0){
a[i]=1;
return;
}
for(int j=i-1;j>=0;--ji){
if(a[i]==a[j]&&a[i]!=9){
++a[i];
a[i]%=10;
return;
}
else if(a[i]==a[j]&&a[i]==9){
a[j-1]++;
a[j-1]%=10;
FOR(k, 1,size-j){
a[k]=k;
}
return;
}
}
}
}
As the error says, you can't have an array of references. It looks like you're actually trying to pass an array by reference. You can (sort of) do that by changing it to take a pointer to the start of the array:
void repfunc(int a[], int size) // equivalent to "int * a"
Since arrays are convertible to pointers, this will do the right thing if the argument is an array
int a[4] = {1,2,3,4};
repfunc(a, sizeof a / sizeof a[0]);
Alternatively, you could accept a reference to an array of the correct size:
template <size_t size>
repfunc(int (&a)[size])
allowing the size to be deduced automatically
int a[4] = {1,2,3,4};
repfunc(a);
but note that this will only work if a is actually an array; not, for example an pointer to a dynamically allocated array.
C++ Standard 8.3.2/4 clearly says that:
There shall be no references to references, no arrays of references, and no pointers to references
Actually a reference must always refer to something - there is no such thing as a null reference. This is why there can be no arrays of references, as there is no way to default instantiate references inside an array to a meaningful value.
-Source is Here.
And also By origin array is accessed via pointer arithmatic. So if we want to support array of reference we have to support pointer to reference, as per standard which is not possible.
These are reason array of reference is not possible. Which is what you were doing. And as Mike Seymour mentioned :
void repfunc(int a[], int size) is perfectly ok for your case.

Using variables versus pointers to variables as parameters for a function

When a function requires a pointer as an argument (and not the variable that the pointer references), is this simply because of the size of the values that would be passed to the function?
I can understand how someone would want to pass a pointer to an array or struct, rather than passing the entire array or struct, but are their other reasons for this decision? For example, a function requiring a pointer to an int (4 bytes) rather than the int (4 bytes) itself.
If you would like your function to change the value of a parameter (such as an int), then you must pass in a pointer to it. Otherwise, any changes that your function makes will be made on a copy.
In general, so-called "output parameters" in C and C++ are often pointers to whatever variable is to be affected by the function.
As for arrays, C doesn't actually permit one to pass a large block of memory to a function, and so we have no choice but to pass a pointer.
(Edit: as discussed in the comments, this answer applies to pointers only. In C++, one may also use references)
In C++ you would pass built in types by value except when you want to modify them in the method or function and have the modification apply to the original variable.
You can pass by reference or by pointer. Some people prefer to pass by pointer if they are going to modify the input as it is more explicit as you have to dereference the pointer.
IE:
void foo(int& a, int* b)
{
a = 1; // This modifies the external variable, but you can't see that just looking at this line
*b = 1; //explicitly modifying external variable
}
int z = 0;
int y = 0;
foo(y, &z); //z is explicitly being allowed to be modified, that y can be too isn't apparent until you look at the function declaration.
Others think this passing pointers is ugly and don't like it.
The best practice for passing large types around is by const reference, which says you won't be modifying the instance.
The answer in one line is: pass-by-(pointer/reference)-to-const if you are dealing with input parameters to non fundamental types, pass-by-value if you are dealing with input parameters to fundamental types, pass-by-(pointer/reference) otherwise. As pointed out in the comments (thanks TonyD) this last "rule" is meant to be an optimisation over using pass-by-(pointer/reference)-to-const; it is likely unnecessary, but it's worth nowing. Note that passing by reference to const does not inficiate the ability to call a function with a temporary (be it a literal or a result from a function call) parameter.
Several distinctions have to made to answer this question appropriately. First of all C and C++ are two different beasts: the only options in C are pass-by-value (pbv), pass-by-pointer (pbp) and pass-by-pointer-to-const (pbptc). In C++ you have also the option to pass-by-reference (pbr) and pass-by-reference-to-const (pbrtc). Secondly, there is the distinction between an input parameter and an (input/)output parameter; when a parameter belongs to the second class you have no options but pbp or pbr (if appliable, i.e. if using c++). As for input parameters, the considerations to be made are more subtle. Alexandrescu addresses this issue in his book "Modern C++"
you sometimes need to answer the following question: Given an
arbitrary type T, what is the most efficient way of passing and
accepting objects of type T as arguments to functions? In general, the
most efficient way is to pass elaborate types by reference and scalar
types by value. (Scalar types consist of the arithmetic types
described earlier as well as enums, pointers, and pointers to
members.) For elaborate types you avoid the overhead of an extra
temporary (constructor-plus-destructor calls), and for scalar types
you avoid the overhead of the indirection resulting from the
reference.
(of course, for input parameters, he is referring to pbrtc). Similarly, you should choose to pbptc for "elaborate" types in C.
Finally, if you are using C++, you can automate this choice by using "type traits" (either the standard ones or custom written ones, see Modern C++ for more on this). Type traits allow you to automatically know if a type is a fundamental type, if it is a reference already (in which case you cannot pass it by reference, because C++ doesn't allow references to references) and all kind of meaningful stuff. By means of type_traits, for example, you can write something like this
#include <type_traits>
typedef int& my_type;
void f(const std::add_lvalue_reference<my_type> a){
}
typedef int my_type2;
void g(const std::add_lvalue_reference<my_type2> a){
}
int main() {
}
Of course, this is a made up example, but you can see the utility of the approach, which is much greater if you are using templates. Notice that type_traits are part of the c++11 std library, if you are not using c++11 you have to make your own (or use some library as loki)
When you want to change the int variable, you can use reference too.
For an array, the array name is just a pointer to the first element, when it's used as a parameter passed to a function, it will change to ordinary pointer, so you must pass the number of the elements in the array as a parameter.
Using variables versus pointers to variables as parameters for a function
General recommendations:
If a function does not change parameter, pass by value.
#include <iostream>
int test(int arg){
std::cout << arg;
}
int main(int argc, char** argv){
int a = 6;
test(a);
return 0;
}
If a function needs to change passed parameter, pass by reference.
#include <iostream>
int test(int &arg){
arg = 6;
}
int main(int argc, char** argv){
int a = 0;
test(a);
std::cout << arg;
return 0;
}
If a function does not need to change parameter, but parameter is BIG, pass by const reference.
If a function neeeds to change passed parameter AND this parameter is optional, pass by pointer.
#include <iostream>
int test(int *arg){
if (arg)
*arg = 6;
}
int main(int argc, char** argv){
int a = 0, b = 1;
test(0);
test(&b);
std::cout << a << std::endl << b << std::endl;
return 0;
}
If a function does not neeed to change passed parameter, parameter is big and parameter is optional, pass by pointer to const.
Reasoning: references and pointers can be used to modify values "outside" of function, but references cannot be set to 0/NULL.
pointer to an int (4 bytes)
Depending on the platform, pointer to int may not be 4 bytes big. On 64bit system it'll be 8bytes big, for example.
Returning pointer to int makes sense if that function allocates memory block. Returning pointer/reference to int makes sense if this function is is used as a "selector" and you need to write into returned value.
#include <iostream>
int& getMaxVal(int &a, int &b){
return (a > b)? a: b;
}
int main(int argc, char** argv){
int i = 3, j = 4;
std::cout << i << " " << j << std::endl;
getMaxVal(i, j) /= 2;
std::cout << i << " " << j << std::endl;
return 0;
}

Determining the type of an expression

Sometimes I need to learn the type of an expression while programming in C or C++. Sometimes there's a good IDE or existent documentation to help me, but sometimes not. I often feel such a construct could be useful:
void (*myFunc)(int);
printf("%s", nameoftype(myFunc)); //"void (*)(int)"
int i, unsigned int u;
printf("%s", nameoftype(i+u)); //"unsigned int"
This is especially true for C++; think accessors of const objects - do they return a const reference or a copy? Think dynamic casts and templated classes.
How can I do this? (i.e. learn the type of an expression)
I use GCC but as far as I know, it does not have such an extension. So I guess I'm curious as to how people solve this problem. (Both compile-time and runtime solutions welcome.)
Sometimes I just do:
int ***a = expression;
and look for the "<expression type> cannot be assigned to pointer-to^3 int" error. This seems to be the most portable workaround.
C++ has a typeid operator;
typeid(expression).name()
would return an implementation-defined name of the type of the expression. Alas, it is usually not human-readable.
What are you looking for? Automatic type inference or looking for the type so you can declare a variable correctly manually? (your own answers look like you want to have the second one). In this case, consider using Geordi:
<litb> make type pointer to function taking pointer to array of 10 int returning void
<geordi> void (*)(int (*)[10])
<litb> geordi: { int a = -1; unsigned int b = 0; cout << ETYPE(a + b), ETYPE_DESC(a + b), (a + b); }
<geordi> rvalue unsigned int, rvalue unsigned integer, 4294967295
<litb> geordi: << TYPE_DESC(void (*)(int (*)[10]))
<geordi> pointer to a function taking a pointer to an array of 10 integers and returning nothing
Automatic type inference is not currently possible without helper libraries like boost.typeof, which will use compiler extensions like __typeof__ for GCC. Next C++ will get auto (with different semantics than current auto) and will be able to do that, together with decltype to get the type of an expression.
If you can live with getting out of local context, you can always create a function template like this:
template<typename T> void f(T t) { /* ... */ }
int main() { int a = -1; unsigned int b = 0; f(a + b); }
Try Boost.Typeof to see if it fits.
gcc has typeof() at compile time. It works like sizeof().
http://gcc.gnu.org/onlinedocs/gcc/Typeof.html has more information.