find sizeof char array C++ - c++

im trying to get the sizeof char array variable in a different function where it was initialize however cant get the right sizeof. please see code below
int foo(uint8 *buffer){
cout <<"sizeof: "<< sizeof(buffer) <<endl;
}
int main()
{
uint8 txbuffer[13]={0};
uint8 uibuffer[4] = "abc";
uint8 rxbuffer[4] = "def";
uint8 l[2]="g";
int index = 1;
foo(txbuffer);
cout <<"sizeof after foo(): " <<sizeof(txbuffer) <<endl;
return 0;
}
the output is:
sizeof: 4
sizeof after foo(): 13
desired output is:
sizeof: 13
sizeof after foo(): 13

This can't be done with pointers alone. Pointers contain no information about the size of the array - they are only a memory address. Because arrays decay to pointers when passed to a function, you lose the size of the array.
One way however is to use templates:
template <typename T, size_t N>
size_t foo(const T (&buffer)[N])
{
cout << "size: " << N << endl;
return N;
}
You can then call the function like this (just like any other function):
int main()
{
char a[42];
int b[100];
short c[77];
foo(a);
foo(b);
foo(c);
}
Output:
size: 42
size: 100
size: 77

You cant. In foo you are asking for the size of a "uint8_t pointer". Pass the size as a separate parameter if you need it in foo.

Some template magic:
template<typename T, size_t size>
size_t getSize(T (& const)[ size ])
{
std::cout << "Size: " << size << "\n";
return size;
}

Related

find size of parameterized array

I'm simply trying to get the size of an array passed as a parameter in a function, but I dont understand why the sizeof(k)/sizeof(k[0]) just returns one, when it works fine in the scope where it was declared, what am i missing here?
Heres the code:
#include <iostream>
using namespace std;
int fn(int k[]){
cout << "size in function :" << sizeof(*k) / sizeof(k[0]) << endl; //returns 1 for some reason
//cout << "size in function :" << end(k)-begin(k) << endl; // can't find begin-end fitting function?
int m = *max(&k[0], &k[sizeof(k)/sizeof(int)]);
return m;
}
int main()
{
int k[] = { 1,2,3,4,5,6,7 };
int s = size(k);
cout << "size :" << sizeof(k) / sizeof(k[0]) << endl;
cout << "max: " << fn(k);
return 0;
}
The size of an array only "exists" at compile-time. By the time the code is compiled, arrays are nothing more than pointers.
So if you want a function to accept a sized array, then the size needs to be passed at compile-time, which means it has to be a template parameter.
template<std::size_t N>
int fn(int (&k)[N]){
cout << "size in function :" << N << endl;
cout << "size in function :" << end(k)-begin(k) << endl;
int m = *max(begin(k), end(k));
return m;
}
what am i missing here?
The type of the parameter is int* (after having been adjusted from an array of unknown bound).
sizeof(k)/sizeof(int)
You're dividing the size of a pointer with the size of an integer. That division has nothing to do with the size of the array whose element is being pointed at.
when it works fine in the scope where it was declared
That's because the type of that k isn't int*. The type of the that k is int[7].
find size of parameterized array
The type of a parameter is never an array in C++. If you declare a function parameter to be an array, then the type will be adjusted to be a pointer to element of such array.
If the type of the parameter is pointer, and if that pointer points to element of an array, then there is no general way to find out the size of the array in question.
Some arrays contain a sequence that is terminated by an element with a sentinel value. You can determine the length of such sequence by performing a linear search for the sentinel value. Null terminated strings are a common example of such sequences.
Old fashioned, C style is to pass the size of the array as separate parameter:
int fn(int k[], std::size_t size);
// usage
int k[] = { 1,2,3,4,5,6,7 };
fn(k, std::size(k));
A more modern approach is to combine the pointer and the size in a class. There is a class template for such purpose in the standard library:
int fn(std::span<int> k);
// usage
int k[] = { 1,2,3,4,5,6,7 };
fn(k);

Unexpected results with array and array as argument [duplicate]

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);
}

Is there a way to access members of a struct

I want to be able to find the size of the individual members in a struct. For example
struct A {
int a0;
char a1;
}
Now sizeof(A) is 8, but let's assume I am writing a function that will print the alignment of A as shown below where "aa" represents the padding.
data A:
0x00: 00 00 00 00
0x04: 00 aa aa aa
*-------------------------
size: 8 padding: 3
In order for me to calculate padding, I need to know the size of each individual members of a struct. So my question is how can I access to individual members of a given struct.
Also, let me know if there is another way to find the number of padding.
A simple approach would be to use sizeof operator (exploiting the fact that it does not evaluate its operand, only determines the size of the type that would result if it was evaluated) and the offsetof() macro (from <cstddef>).
For example;
#include <iostream>
#include <cstddef>
struct A
{
int a0;
char a1;
};
int main()
{
// first calculate sizes
size_t size_A = sizeof(A);
size_t size_a0 = sizeof(((A *)nullptr)->a0); // sizeof will not dereference null
size_t size_a1 = sizeof(((A *)nullptr)->a1);
// calculate positions
size_t pos_a0 = offsetof(A, a0); // will be zero, but calculate it anyway
size_t pos_a1 = offsetof(A, a1);
// now calculate padding amounts
size_t padding_a0 = pos_a1 - pos_a0 - size_a0; // padding between a0 and a1 members
size_t padding_a1 = size_A - pos_a1 - size_a1;
std::cout << "Data A:\n";
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << pos_a0;
size_t i = pos_a0;
while (i < pos_a0 + size_a0) // print out zeros for bytes of a0 member
{
std::cout << " 00";
++i;
}
while (i < pos_a1) // print out aa for each padding byte after a_0
{
std::cout << " aa";
++i;
}
std::cout << std::endl;
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << pos_a1;
while (i < pos_a1 + size_a1) // print out zeros for bytes of a1 member
{
std::cout << " 00";
++i;
}
while (i < size_A) // print out aa for each padding byte after a_1
{
std::cout << " aa";
++i;
}
std::cout << std::endl;
std::cout << "size: " << size_A << " padding: " << padding_a0 + padding_a1 << std::endl;
}
You can work this out if you know the content of the struct. Passing usually works like this,
Assume that your struct is this.
struct A {
int a0; // 32 bits (4 bytes)
char a1; // 8 bits (1 byte)
};
But this is not memory efficient as if you pack these structs in memory, you might get some fragmentation issues thus making the application slower. So the compiler optimizes the struct like this and the final struct to the compiler would look something like this.
struct A {
int a0;
char a1;
// padding
char __padd[3]; // 3 * 1 byte = 3 bytes.
/// Adding this padding makes it 32 bit aligned.
};
Now using this knowledge, you can see why its not easy to get the padding of an object without knowing the content of it. And paddings aren't always placed at the end of the object. For example,
struct Obj {
int a = 0;
char c = 'b';
// Padding is set here by the compiler. It may look something like this: char __padd[3];
int b = 10;
};
So how to get the padding of the struct?
You can use something called Reflection to get the content of the struct at runtime. Then workout the sizes of the data types in the struct and then you can calculate the padding by deducting the size of the previous type and the next type which gives you how the padding would look like.
As other answers have said, the offsetof macro is clearly the best solution here, but just to demonstrate that you could find the positions of your members at run time by looking at the pointers:
#include <iostream>
struct A
{
char x;
int y;
char z;
};
template <typename T>
void PrintSize ()
{
std::cout << " size = " << sizeof(T) << std::endl;
}
void PrintPosition (char * ptr_mem, char * ptr_base)
{
std::cout << " position = " << ptr_mem - ptr_base << std::endl;
}
template <typename T>
void PrintDetails (char member, T * ptr_mem, A * ptr_base)
{
std::cout << member << ":" << std::endl;
PrintSize<T>();
PrintPosition((char*) ptr_mem, (char*) ptr_base);
std::cout << std::endl;
}
int main()
{
A a;
PrintDetails('x', &a.x, &a);
PrintDetails('y', &a.y, &a);
PrintDetails('z', &a.z, &a);
}
Output on my machine:
x:
size = 1
position = 0
y:
size = 4
position = 4
z:
size = 1
position = 8
(Surprisingly, on my intel, with gcc/clang, A is of size 12! I thought that the compiler did a better job of rearranging elements)
To calculate the padding of a structure, you need to know the offset of the last member, and the size:
Concisely, if type T has a member last which is of type U, the padding size is:
sizeof(T) - (offsetof(T, last) + sizeof(U))
To calculate the total amount of padding in a structure, if that is what this question is about, I would use a GCC extension: declare the same structure twice (perhaps with the help of a macro), once without the packed attribute and once with. Then subtract their sizes.
Here is a complete, working sample:
#include <stdio.h>
#define X struct { char a; int b; char c; }
int main(void)
{
printf("%zd\n", sizeof(X) - sizeof(X __attribute__((packed))));
return 0;
}
For the above structure, it outputs 6. This corresponds to the 3 bytes of padding after a necessary for the four-byte alignment of b and at the end of the structure, necessary for the alignment of b if the structure is used as an array member.
The packed attribute defeats all padding, and so the difference between the packed and unpacked structure gives us the total amount of padding.

How can I calculate size of Array in C++

I had the online coding interview today and I really struggled while trying to calculate the size of the array.
Could you please help me with how can I measure the sizeof array here? I tried my best but no luck please help here.
#include<iostream>
#include<map>
#include<vector>
using namespace std;
void arraysize(int* a) {
cout << "size1: "<<sizeof(a) << endl;
cout << "size2: " << sizeof(a[0]) << endl;;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
arraysize(array1);
return 0;
}
Result:
size1: 4
size2: 4
In most cases, when you pass an array to a function, the array will be converted to a pointer. This is called an array-to-pointer decay. Once this decay happens, you lose the size information of the array. That is, you can no longer tell the size of the original array from the pointer.
However, one case in which this conversion / decay will not happen is when we pass a reference to the array. We can take advantage of this property to get the size of an array.
#include<iostream>
template<typename T, size_t N>
size_t asize(T (&array)[N])
{
return N;
}
int main()
{
int array1[] = { 1,2,3,4,5,6,7,8 };
std::cout << asize(array1) << std::endl; // 8
return 0;
}
In the above case, to the template function asize, we pass a reference to an array of type T[N], whose size is N. In this case, it is array type int[8]. So the function returns N, which is size 8.
C style array's decay to pointer's when passed to a function like this.
The first cout statement is printing the size of a pointer on your machine.
The second cout statement is printing the size of an integer.
Use one of the following solutions in order to pass the size of the array to the function.
template<std::size_t N>
void ArraySize( int ( &array )[ N ] )
{
std::cout << "Array size: " << N << '\n';
}
void ArraySize( int* array, std::size_t size )
{
std::cout << "Array size: " << size << '\n';
}
template<std::size_t N>
void ArraySize( std::array<int, N>& array )
{
std::cout << "Array size: "<< array.size( ) << '\n';
}
sizeof(a) returns the number of bytes in array,
sizeof(int) returns the number of bytes in an int,
ergo
sizeof(a)/sizeof(int) returns the array length
Easiest way to get the size of an array:
#include <iostream>
using namespace std;
int main(void) {
int ch[5], size;
size = sizeof(ch) / sizeof(ch[0]);
cout << size;
return 0;
}
Output: 5
simply divide sizeof(array1) by sizeof(int). it will give you total element in array. because sizeof(array1) will give total bytes in the array. for example sizeof(array1) = int * 8 because your array is int so int is 4 byte answer is 4*8 = 32.Now you have to divide it again by 4 cause its in byte.
cout << "Size of the Array is : " << sizeof(array1)/sizeof(int) << endl;
put above code in your main function to get result

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*.