In Visual Studio 2019, I have written the following test codes, but the results confused me.
#include <iostream>
using namespace std;
template<class T, class Func>
int call(T x, Func f) { return f(x); }
int square(int x) { return x * x; }
int main() {
int (*func0) (int) = square; // line 0, OK
//int (func1)(int) = square; // line 1, wrong
int (__cdecl *func1) (int) = square; // line 2, OK
//int (__cdecl func2)(int) = square; // line 3, wrong
cout << ((int(__cdecl*)(int)) square)(5) << endl; // line 4, OK
//cout << ((int(__cdecl)(int)) square)(5) << endl; // line 5, wrong
cout << call<int, int (*)(int)>(5, square) << endl; // line 6, OK
//cout << call<int, int ()(int)>(5, square) << endl; // line 7, wrong
cout << call<int, int(__cdecl*)(int)>(5, square) << endl; // line 8, OK
cout << call<int, int(__cdecl)(int)>(5, square) << endl; // line 9, OK
return 0;
}
(I am aware that I can omit the types when using call, but this is an experiment.)
I thought I was able to understand everything from line 0 to line 7. What I had in mind is that square is a funtion pointer, so it should have type int (*) (int) or perhaps int(__cdecl*) (int), and these two are either identical or can be casted to each other (I didn't change the calling convention of the project, so the default is __cdecl).
However, I was surprised that both line 8 and line 9 compile and run correctly. Why does this happen?
By comparing lines 6, 7 with lines 8, 9, I think the problem comes from adding __cdecl, but in Microsoft Docs nothing like this is mentioned.
I then printed out the types:
// ...
cout << typeid(square).name() << endl; // output: int __cdecl(int)
cout << typeid(*square).name() << endl; // output: int __cdecl(int)
cout << typeid(&square).name() << endl; // output: int(__cdecl*)(int)
cout << (typeid(square) == typeid(int(*) (int))) << endl; // output: false
cout << (typeid(square) == typeid(int(__cdecl) (int))) << endl; // output: true
cout << (typeid(square) == typeid(int(__cdecl*) (int))) << endl; // output: false
cout << (typeid(square) == typeid(*square)) << endl; // output: true
// ...
It seems that square indeed has type int (__cdecl) (int). Also, I don't understand why square and *square are of the same type...
Could someone explain these phenomena to me?
square and *square are the same type because functions decay, just like arrays do, to pointers, except (just like arrays) under certain contexts. In particular, decay is suppressed under typeid and &, but not under *, so typeid(square) gives you the type of square, int (__cdecl)(int), while typeid(*square) means typeid(*&square) means typeid(square) gives the same thing. This leads to the odd fact that you can write as many *s as you want and they will all do nothing: *************square is the same as square.
Now, to the rest of your question, you wrote the type "function taking int returning int" wrong. int ()(int) means "function taking no arguments returning function taking int returning int". You wanted int(int). Then this works:
cout << call<int, int(int)>(5, square) << "\n"; // line 7, fixed (FYI: endl is not normally necessary)
Because now call has arguments list (int x, int f(int)), and a parameter declaration of function type is automatically adjusted to have pointer to function type, making call<int, int(int)> functionally identical to call<int, int (*)(int)>. (This does not work for variable declarations or casts, so lines 1, 3, 5 remain incorrect.) The extra parentheses caused the type to be misinterpreted. Line 9 works because putting __cdecl inside the parentheses makes them not be misinterpreted (instead of being the function declarator, they become grouping symbols).
cout << call<int, int (__cdecl)(int)>(5, square) << "\n"; // line 9, OK
Again, the type of call's parameter is adjusted. int (__cdecl f)(int) becomes int (__cdecl *f)(int), which makes line 9 functionally identical to line 8.
The error with the line:
int (func1)(int) = square; // line 1, wrong
is that you are missing a '*', it needs to be:
int (*func1)(int) = square; // line 1, wrong
same with
//int (__cdecl func2)(int) = square; // line 3, wrong
cout << ((int(__cdecl)(int)) square)(5) << endl; // line 5, wrong
needs to be
cout << ((int(__cdecl*)(int)) square)(5) << endl; // line 5, wrong
Related
Can anyone please explain!
While referring ArrayDecay, I was stuck at this...,
void fun(int (&p)[7])
{
cout << sizeof(p) << endl;
}
int main()
{
int a[7] = {1, 2, 3, 4, 5, 6, 7,};
cout << "Actual size of array is: ";
cout << sizeof(a) <<endl;
// Calling function by reference
fun(a);
return 0;
}
I know the difference between (*p)[] and *p[] and their functioning.
But, can't figure out what (&p)[] is!.
In the context of function argument declarations, the & means reference.
So the function fun accepts one argument, which is a reference to an array of 7 integer elements.
The comment should have been a pretty big hint:
// Calling function by reference
fun(a);
I'm having a struct with an array which is static and want to access the data in that array. Tried to use the new C++11 for loops and also do it without the for loop and just print array[1]. See the second cout in the main function.
I already know that the problem have to do something with the fact that the array in the struct tCalcAngularEstimationFromComplexData_32 is adjusted as a pointer type. Therefore I tried to use for (const auto &arr : &test_data_1) but wasn't able to solve it.
Thanks.
typedef struct tComplex_R {
float real;
float imag;
}tComplex_R;
typedef struct tOutputVRx_R {
float range;
float vel;
tComplex_R AmpLinRx[1];
} tOutputVRx_R;
typedef struct tCalcAngularEstimationFromComplexData_32{
int antennas_azimuth;
int antennas_elevation;
tOutputVRx_R dataset1[32]; //Range Velocity and Complex Data for 32 Antennas
} tCalcAngularEstimationFromComplexData_32;
static tCalcAngularEstimationFromComplexData_32 tCalcAngEstComplexData_dataset_1 = {
5, 90,
{{1, 3, {10, 15}},
{2, 4, {11, 16}}
}
};
int main(){
tCalcAngularEstimationFromComplexData_32 test_data_1 = tCalcAngEstComplexData_dataset_1;
cout << "Range 1: " << test_data_1.dataset1->range << endl;
cout << "Range 2: " << test_data_1.dataset1[1]->range << endl; //Not working
for (const auto &arr : test_data_1) {
cout << "Range: " << arr.dataset1->range << endl;
}
}
Range-based for loops need to have access to the bounds of what you're iterating.
As noted on the relevant cppreference page, there are three ways:
It is an array of known size (which is the case for your dataset1 member)
my_struct::begin() and my_struct::end() are defined
begin(my_struct&) and end(my_struct&) are defined
As for this line:
cout << "Range 2: " << test_data_1.dataset1[1]->range << endl; //Not working
It is because dataset1[1] is not a pointer but a reference, so you don't use -> but . instead.
See a working example on godbolt
This question already has answers here:
What is the purpose of sized array as function argument is c and c++?
(2 answers)
Closed 1 year ago.
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all? My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
#include <iostream>
using namespace std;
void printArray(int intArray[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
int main()
{
int array1[1] = {1}; // Smaller array size than in the function signature
cout << "\nInvocation 1\n";
printArray(array1);
int array2[4] = {1, 2, 3, 4}; // Smaller array size than in the function signature
cout << "\nInvocation 2\n";
printArray(array2);
int array3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // Larger array size than in the function signature
cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, not the way you do it.
This would on the other hand make intArray a reference to the array you pass as an argument:
void printArray(int (&intArray)[5]) {
for (int i = 0; i < 5; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
A more generic form would be to make it a function template. This would then be instantiated once for each array size you call it with:
template<std::size_t N>
void printArray(int (&intArray)[N]) {
for (int i = 0; i < N; i++) {
cout << intArray[i] << " ";
}
cout << endl;
}
Does defining a sized array in a function signature (as opposed to the more commonly used unsized array or pointer syntax) have any bearing at all?
No, it has not, the passed array argument will always decay to a pointer to its first element, placing a size is indeed pointless from the compiler standpoint, it will ignore it, having void printArray(int intArray[5]){...}, void printArray(int intArray[]){...} or void printArray(int* intArray){...} will be basically the same.
My compiler is ignoring it completely, as the following sample code shows (which runs, although it prints some garbage values when a smaller-sized array is passed).
Which makes sense because in the loop you are accessing elements outside the bounds of the array, so the behavior is undefined.
This is how I would do it using std::array
#include <array>
#include <iostream>
template<typename type_t, std::size_t N>
void printArray(const std::array<type_t,N>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
void printArray_s(const std::array<int, 5>& values)
{
for (const auto& value : values)
{
std::cout << value << " ";
}
std::cout << std::endl;
}
// helper function to avoid having to type value of N in std::array (syntactic sugar)
// used for array3
template<typename array_type, typename... args_t>
constexpr auto make_array(const args_t&&... values)
{
return std::array<array_type, sizeof...(args_t)>{ static_cast<array_type>(values)... };
}
int main()
{
// Smaller array size than in the function signature
std::array<int,1> array1{ 1 };
std::cout << "\nInvocation 1\n";
//printArray_s(array1); // <== will correctly give compiler error
// Smaller array size than in the function signature
std::array<int, 4> array2{ 1, 2, 3, 4 };
std::cout << "\nInvocation 2\n";
printArray(array2);
// Larger array size than in the function signature
auto array3 = make_array<int>(1, 2, 3, 4, 5, 6, 7, 8 );
std::cout << "\nInvocation 3\n";
printArray(array3);
return 0;
}
I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo
I am in the middle of making a recursive array function that counts the numbers and adds them together returning them in a recursive function. The function seems to actually work but the number I originally input into the array were 1,2,3,4,5 but the program tells me that those number are 49, 50, 51, 52, 53... Very confused on why this might be happening, any help or insight would be greatly appreciated. Thank you!
#include <iostream>
using namespace std;
const int SIZE = 5;//size of array
int sum(int [], int);//recursive function
int main()
{
int sumArray[SIZE] = { '1', '2', '3', '4', '5'};//array with predetermined values
cout << sumArray[0] << endl;//49
cout << sumArray[1] << endl;//50
cout << sumArray[2] << endl;//51
cout << sumArray[3] << endl;//52
cout << sumArray[4] << endl;//53
cout << sum(sumArray, SIZE) << endl;//displays the amount 255 (5 elements added)
system("pause");
return 0;
}
int sum(int sumArray[], int size)
{
if (size == 1)
return sumArray[size - 1];
else
{
cout << size << endl;
return sumArray[size - 1] + sum(sumArray, size - 1);
}
}
You are actually put in the array ASCII-codes of the numbers: '1' is really a char with code 49 which is converted to int 49. Write as follows:
int sumArray[SIZE] = { 1, 2, 3, 4, 5 };
This is called implicit conversion - look at the section "Integral promotion."