This question already has answers here:
Arrays passed to function in C++ giving different lengths
(5 answers)
Closed 5 years ago.
Consider the code below. This generates the following output:
Length: 64
Testfn: 8
Length again: 64
I am having trouble understanding why the output at the test-function is not equal to the output at the main function. Taking into account that the output at the test-function is equal to 8, I assume that this is because sizeof(arg) gets the size of the pointer instead of the array itself.
This would all seem very logical to me, but why doesn't sizeof give that same value in the main function? And how would I fix it? I have tried several things with dereferencing, but this does not seem to give any difference whatsoever.
#include <iostream>
void test(int arg[]) {
std::cout << "Testfn: " << sizeof(arg) << std::endl;
}
int main() {
int int_arr[16];
std::cout << "Length: " << sizeof int_arr << std::endl;
test(int_arr);
std::cout << "Length again: " << sizeof int_arr << std::endl;
}
The function parameter
void test(int arg[]) {
is adjusted to pointer to type int. That is the following function declarations
void test(int arg[16]);
void test(int arg[]);
void test(int *arg);
are equivalent.
So inside the function there is used sizeof( int * ) that depending on the using platform usually equal to either 4 or 8.
You could declare the function in C++ like
void test(int ( &arg )[16]) {
std::cout << "Testfn: " << sizeof(arg) << std::endl;
}
that is to declare the parameter as reference to the array and in this case you will get the expected result.
If you use C++11 or higher, the std::array is what you need:
#include <iostream>
#include <array>
template<size_t N>
void test(const std::array<int, N>& arg) {
std::cout << "Testfn: " << arg.size() << std::endl;
}
int main() {
std::array<int, 16> int_arr;
std::cout << "Length: " << int_arr.size() << std::endl;
test(int_arr);
std::cout << "Length again: " << int_arr.size() << std::endl;
}
Related
This question already has an answer here:
When passing an array to a function in C++, why won't sizeof() work the same as in the main function?
(1 answer)
Closed 1 year ago.
Forgive me for this possibly dumb question. Consider this:
int foo(int* arr) {
std::cout << arr << "(" << sizeof(arr) << ")";
}
int main()
{
int x[] = {0, 1, 2, 3, 4};
foo(x);
std::cout << " " << x << "(" << sizeof(x) << ")";
}
Output: 0x7c43ee9b1450(8) 0x7c43ee9b1450(20) - Same address, different size.
My understanding is that the function argument is an address specific to the first element of the array, so the size is 8 bytes, and the same should be true for the variable in main too; So how come the size of the variable outside of the function represent the whole array (4 bytes int times 5 elements = 20)? How could I possibly determine from inside the function how large an array actually is?
This is because the types are not the same inside and out side the function.
If you make sure the type is the same inside and outside the function you should get the same result.
int foo(int (&arr)[5])
{
std::cout << arr << "(" << sizeof(arr) << ")";
return 0;
}
The problem is that arrays decay into pointers at the drop of a hat. So if you pass an array to a function it will easily be converted into a pointer. That is what is happening here.
int foo(int* arr)
// ^^^^ Notice this is not an array.
// It is simply a pointer to an integer
// The array has decayed into a pointer to the
// first element in the array.
{
std::cout << arr << "(" << sizeof(arr) << ")";
return 0;
}
How could I possibly determine from inside the function how large an array actually is?
This is actually a real problem with C. In C they solved this by getting you to pass the size of the array as a second parameter:
int foo(int* arr, std::size_t size);
Then call it from main as:
foo(arr, sizeof(arr)/sizeof(arr[0])); // This always works as it done
// at compile time and not runtime
In C++ we don't usually use C-arrays but prefer std::vector or std::array as the size is easily retrievable. Generally we use a container type C as they are duck types of Container:
template<typename C>
int foo(C& container)
{
std::cout << "(" <<container.size() << ")";
return container.size();
}
When passing an array like that you loose ALL the size information.
So the called function is flying blind with regard to the array size.
In C++ is makes much more sense to use std::array (fixed size arrays), and std::vector (changing size arrays). It is much clearer what your intent is when you pass them to functions. There will be less mistakes and less memory access issues in your code.
I hope I don't scare you too much with the template version.
The vector variant is more easy, but may use a bit more memory at runtime.
#include <array>
#include <vector>
#include <iostream>
template<size_t N>
size_t foo(const std::array<int,N>& arr)
{
for (const auto n : arr) std::cout << n << " ";
std::cout << "(" << arr.size() << ")" << std::endl;
return arr.size();
}
size_t foo(const std::vector<int>& arr)
{
for (const auto n : arr) std::cout << n << " ";
std::cout << "(" << arr.size() << ")" << std::endl;
return arr.size();
}
int main()
{
std::array<int,5> x{ 0, 1, 2, 3, 4 };
std::vector<int> y{ 0, 1, 2, 3, 4 };
auto size_x = foo(x);
auto size_y = foo(y);
}
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
So when I have this function, and I print it to the console via multiple statements, I get the expected results:
0
1
But when I print the function out through just one cout statement on the same line, I get:
3 2
(This is after the initial 0 and 1 that were previously printed)
Why does it print backwards?
#include "stdafx.h"
#include <iostream>
using namespace std;
int addOne()
{
static int s_num = -1;
return ++s_num;
}
int main()
{
cout << addOne() << "\n";
cout << addOne() << "\n";
cout << addOne() << " " << addOne() << "\n";
return 0;
}
You are actually stumbling on unspecified behavior. In this context, and any other such context where the operators are of the same precedence, the function calls can be evaluated in any order. In this case, the compiler chose to evaluate the second function call before the first, but other compilers might do it differently.
In C++ macros you can use #var to get the literal string of the argument passed:
#define PRINT_SIZE(type) \
(std::cout << sizeof(type) << " " << #type << std::endl)
Using this macro, I can write a very simple program which will give me the lengths of specific types on my machine:
PRINT_SIZE(bool);
PRINT_SIZE(char);
…
This does work but I would like to use C++ templates instead. Obtaining the size is easy with the following template function:
template <typename T>
void print_size() {
std::cout << sizeof(T) << std::endl;
}
I can call this function with any type and it will output the size:
print_size<bool>();
print_size<char>();
…
Is there any way I could get a literal "bool" from this anywhere such that the output would be as nice as the one with macros?
It can sortof be done using RTTI (runtime type inference) using typeid:
#include <iostream>
#include <typeinfo>
template <typename T>
void print_size() {
T a;
std::cout << typeid(a).name() << ": " << sizeof(T) << std::endl;
}
int main(){
print_size<bool>();
print_size<char>();
print_size<long>();
return 0;
}
This outputs:
b: 1
c: 1
l: 8
You can use typeid() as in:
int i;
cout << typeid(i).name(); // Most likely will print int but g++ prints i
cout << typeid(int).name(); // Also most likely will print int but g++ prints i
Note that the name it returns depends on the compiler and may be some unusual form of the type. More information here.
Edit:
g++ (4.8) prints only the first letter of fundamental types. For user defined classes, it prints the number of characters in the name followed by the name. Ex:
#include <iostream>
#include <typeinfo>
class myclass
{
myclass() {}
};
class my
{
my() {}
};
int main()
{
std::cout << typeid(int).name() << std::endl;
std::cout << typeid(bool).name() << std::endl;
std::cout << typeid(myclass).name() << std::endl;
std::cout << typeid(my).name() << std::endl;
}
Produces the following output:
i
b
7myclass
2my
This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 7 years ago.
Can you tell me the difference between the source 1 and 2?
The book says the first one is call by address(pointer) and the second one is call by reference, but i don't exactly get those two sources.
Please explain those sources to me please, thank you in advance.
1.
#include <iostream>
using namespace std;
void absolute(int *a);
void main()
{
int a = -10;
cout << "Value a before calling the main function = " << a << endl;
absolute(&a);
cout << "Value a after calling the main function = " << a << endl;
}
void absolute(int *a)
{
if (*a < 0)
*a = -*a;
}
2.
#include <iostream>
using namespace std;
void absolute(int &a);
void main()
{
int a = -10;
cout << "Value a before calling the main function" << a << endl;
absolute(a);
cout << "Value a after calling the main function" << a << endl;
}
void absolute(int &a)
{
if (a < 0)
a = -a;
}
In terms of what happens at the CPU level, pointers and references are exactly the same. The difference lies in the compiler, it won't let you do a delete on a reference (and there's less typing)
So in your code both functions do the same thing.