Variable length Struct NonStandard in C++11? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is the “struct hack” technically undefined behavior?
I checked if zero length arrays were allowed in C++11. It appeared they aren't. From 8.3.4 Arrays [dcl.array]
If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.
Since i cant use zero length arrays Is it possible to use variable length structs while being standard/Well Defined? For example I'd want to do something like the below. How do I make it well defined and standard when the buffer MAY BE EMPTY.
-edit- related: Array of zero length
struct MyStruct {
uint size;
int32 buf[0];//<-- NonStandard!
};
...
auto len=GetLength();
auto ptr=GetPtr();
auto bytelen=len*sizeof(int32);
var p = reinterpret_cast<MyStruct*>(malloc(bytelen))
p->size=len
memcpy(p->buf, ptr, bytelen)
return p;

This is C++, not C. You don't need this flexible array member hack in C++, because you can easily make a template class which can endow any struct with a flexible array past the end and encapsulate the pointer arithmetic calculation and the memory allocation to make it work. Watch:
#include <cstring>
template <typename STRUCT, typename TYPE> class flex_struct {
public:
TYPE *tail()
{
return (TYPE *) ((char *) this + padded_size());
}
// substitute malloc/free here for new[]/delete[] if you want
void *operator new(size_t size, size_t tail)
{
size_t total = padded_size() + sizeof (TYPE) * tail;
return new char[total];
}
void operator delete(void *mem)
{
delete [] (char *) mem;
}
private:
static size_t padded_size() {
size_t padded = sizeof (flex_struct<STRUCT, TYPE>);
if(padded % alignof(TYPE) != 0) {
padded = padded & ~(alignof(TYPE)-1) + alignof(TYPE);
}
return padded;
}
};
struct mystruct : public flex_struct<mystruct, char> {
int regular_member;
};
int main()
{
mystruct *s = new (100) mystruct; // mystruct with 100 chars extra
char *ptr = s->tail(); // get pointer to those 100 chars
memset(ptr, 0, 100); // fill them
delete s; // blow off struct and 100 chars
}

No, you cannot do it compliantly *.
Use a std::vector.
* I'm assuming that C++ doesn't add any rules that contradict C in this area. IMO it's highly unlikely, though I don't have time to verify that at the minute.

The struct hack was never standard. This should be a standard viable replacement:
struct MyStruct {
uint size;
int32 buf[1];
};

Related

new operator overloading in c++ example

I have the following code which I can't understand the status after one line in main.
#include <iostream>
typedef unsigned long size_t;
const int MAX_BUFFER=3;
int buf[MAX_BUFFER]={0}; //Initialize to 0
int location=0;
struct Scalar {
int val;
Scalar(int v) : val(v) { };
void* operator new(size_t /*not used*/) {
if (location == MAX_BUFFER) {
throw std::bad_alloc();
} else {
int* ptr = &buf[location];
if ( buf[location] == 0) {
location++;
} else {
return ptr;
}
}
}
void operator delete(void* ptr) {
size_t my_loc = (int*)ptr - buf;
buf[my_loc] = location;
location = my_loc;
}
};
int main() {
Scalar *s1 = new Scalar(11);
cout << buf[0];
}
Why does the array buf in the end of this code contains the value 11 at the...?
I'm am not sure where the val input plays a role.
I don't understand why you only conditionally increment location after an allocation, and if you increment location, then the function doesn't execute a return statement which is undefined behavior.
Your deallocation strategy is completely broken unless objects are only deallocated in the exact opposite order of allocations. Additionally, after the array element has been used for one allocation, it won't ever be used again due to the assignment in the deallocator.
As for the actual question: the first Scalar allocated is allocated at the same location as the buffer, so the first Scalar and buf[0] share the same memory. As they're both composed of a single int, writes to one might be readable from the other. And when you construct the Scalar, it assigns the value 11 to the shared memory. I think doing this is undefined behavior, but I'm not certain.
The value 11 gets into the buffer thanks to
Scalar(int v) : val(v) { };
that takes the parameter and copies it into the member val.
If the class instance is allocated at the address of the buffer (because of the customized operator::new (size_t) implementation) then it's possible that its first member ends up in the first array element.
Note that this code is totally broken for several reasons already pointed out by Mooing Duck.

sizeof - convert a pointer to an array [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)
I have the following code
int myfunc(char *arr)
{
const int sizearr = sizeof( arr ) / sizeof(char);
}
This yields the size of the pointer, not the size of the char array[17] I passed to the function.
I know that I may use strlen and solve the problem, but is there any way to convert the char*arr pointer back to the char array[17] I passed to the function in order to use the sizeof(char array[17]) ?
If you want to pass an array of 17 chars, you need to pass it by reference (C++ only):
int myfunc(char (&arr)[17])
{
unsigned int const sizearr = sizeof arr;
// ...
}
Or make a template to deduce the size:
template <unsigned int sizearr>
int myfunc(char (&arr)[sizearr])
{
// ...
}
In C, you cannot pass arrays as arguments at all, so it is your responsibility to communicate the array size separately.
Update: As #David suggests, you can fix the array type in C by passing a pointer to the array:
int myfunc(char (*arr)[17])
{
unsigned int const sizearr = sizeof *arr;
// ...
}
int main()
{
char s[17];
return myfunc(&s);
}
No, there is no such way. But in C++ you can make function template parametrized by array size and pass array by reference:
template <size_t size> void myfunc(char (&arr)[size])
{
for(size_t i = 0; i < size; ++i) std::cout << arr[i];
}
// Usage
char array[] = "My char array";
myfunc(array);
No.
There is no such way. The type char * does not contain any information about the "source", i.e. the array. This is why it's said that the array "decays" into a pointer; the pointer has less information than the array.
Also, sizeof (char) is 1.
Not really, because once the array has decayed to a pointer all information regarding its "original" form has been lost. You can always cast the pointer to a char[17] but that's bad practice.
If you really need to have an array, change the function signature to accept an array.

What is T (& var)[N]?

In boost/utility/swap.hpp I have found this piece of code:
template<class T, std::size_t N>
void swap_impl(T (& left)[N], T (& right)[N])
{
for (std::size_t i = 0; i < N; ++i)
{
::boost_swap_impl::swap_impl(left[i], right[i]);
}
}
What are left and right? Are they references to arrays? Is this code allowed by C++ ISO standard 2003 or later?
A reference to an array of type T and length N.
This is a natural extension of C's pointer-to-array syntax, and is supported by C++03.
You could use cdecl.org to try to parse these complex type declarations.
What are left and right? Are they references to arrays? Is this code allowed by C++ ISO standard 2003 or later?
Yes. They're references to arrays.
That means, you can call swap_impl as:
int a[10]; //array
int b[10];
//...
swap_impl(a,b); //correct
But you cannot call swap_impl as:
int *a = new int[10]; //pointer
int *b = new int[10];
//...
swap_impl(a,b); //compilation error
Also note that you cannot do even this:
int a[10];
int b[11];
//...
swap_impl(a,b); //compilation error - a and b are arrays of different size!
Important point:
- Not only arguments must be arrays, but the arrays must be of same size!
This is the way to declare a reference to an array of T (of size N) named left and right. The code is legal C++.
This allows you to pass in:
int ones[5] = { 1,1,1,1,1 };
int twos[5] = { 2,2,2,2,2 };
swap_impl(ones, twos);
Then template type inference will know that you have T = int and N = 5 and do the in-place swap. If you mismatch the types or the size, you get a handy compilation failure.
Yes this is standard C++ allowed from very early on (its basically C with the addition of a reference).
Using typedefs makes it easier to read:
int main()
{
typedef int (&MyArray)[4];
int data[4];
MyArray dataRef = data;
}
It sort of mirrors the function typedef
typedef int (*MyFunc)();

What is sizeof(something) == 0?

I have a template that takes a struct with different values, for example:
struct Something
{
char str[10];
int value;
...
...
};
And inside the function I use the sizeof operator: jump in memory sizeof(Something);
Sometimes I would like to not jump anything at all; I want sizeof to return zero. If I put in an empty struct it will return 1; what can I put in the template to make sizeof return zero?
sizeof will never be zero. (Reason: sizeof (T) is the distance between elements in an array of type T[], and the elements are required to have unique addresses).
Maybe you can use templates to make a sizeof replacement, that normally uses sizeof but is specialized for one particular type to give zero.
e.g.
template <typename T>
struct jumpoffset_helper
{
enum { value = sizeof (T) };
};
template <>
struct jumpoffset_helper<Empty>
{
enum { value = 0 };
};
#define jumpoffset(T) (jumpoffset_helper<T>::value)
What do you think about it?
#include <iostream>
struct ZeroMemory {
int *a[0];
};
int main() {
std::cout << sizeof(ZeroMemory);
}
Yes, output is 0.
But this code is not standard C++.
No object in C++ may have a 0 size according to the C++ standard. Only base-class subobjects MAY have 0 size but then you can never call sizeof on those. What you want to achieve is inachievable :)
or, to put it mathematically, the equation
sizeof x == 0 has no object solution in C++ :)

How to find the size of an int[]? [duplicate]

This question already has answers here:
How do I find the length of an array?
(30 answers)
Closed 2 years ago.
I have
int list[] = {1, 2, 3};
How to I get the size of list?
I know that for a char array, we can use strlen(array) to find the size, or check with '\0' at the end of the array.
I tried sizeof(array) / sizeof(array[0]) as some answers said, but it only works in main? For example:
int size(int arr1[]){
return sizeof(arr1) / sizeof(arr1[0]);
}
int main() {
int list[] = {1, 2, 3};
int size1 = sizeof(list) / sizeof(list[0]); // ok
int size2 = size(list_1); // no
// size1 and size2 are not the same
}
Why?
Try this:
sizeof(list) / sizeof(list[0]);
Because this question is tagged C++, it is always recommended to use std::vector in C++ rather than using conventional C-style arrays.
An array-type is implicitly converted into a pointer-type when you pass it to a function.
Have a look at this.
In order to correctly print the sizeof an array inside any function, pass the array by reference to that function (but you need to know the size of that array in advance).
You would do it like so for the general case
template<typename T,int N>
//template argument deduction
int size(T (&arr1)[N]) //Passing the array by reference
{
return sizeof(arr1)/sizeof(arr1[0]); //Correctly returns the size of 'list'
// or
return N; //Correctly returns the size too [cool trick ;-)]
}
The "standard" C way to do this is
sizeof(list) / sizeof(list[0])
You could use boost::size, which is basically defined this way:
template <typename T, std::size_t N>
std::size_t size(T const (&)[N])
{
return N;
}
Note that if you want to use the size as a constant expression, you'll either have to use the sizeof a / sizeof a[0] idiom or wait for the next version of the C++ standard.
You can't do that for a dynamically allocated array (or a pointer). For static arrays, you can use sizeof(array) to get the whole array size in bytes and divide it by the size of each element:
#define COUNTOF(x) (sizeof(x)/sizeof(*x))
To get the size of a dynamic array, you have to keep track of it manually and pass it around with it, or terminate it with a sentinel value (like '\0' in null terminated strings).
Update: I realized that your question is tagged C++ and not C. You should definitely consider using std::vector instead of arrays in C++ if you want to pass things around:
std::vector<int> v;
v.push_back(1);
v.push_back(2);
std::cout << v.size() << std::endl; // prints 2
Since you've marked this as C++, it's worth mentioning that there is a somewhat better way than the C-style macro:
template <class T, size_t N>
size_t countof(const T &array[N]) { return N; }
This has the advantage that if you accidentally try to pass something other than an array to it, the code simply won't compile (whereas passing a pointer to the C macro will compile but produce a bad result. The disadvantage is that this doesn't give you a compile-time constant, so you can't do something like this:
int a[20];
char x[countof(a)];
In C++11 or newer, you can add constexpr to get a compile-time constant:
template <class T, size_t N>
constexpr size_t countof(const T &array[N]) { return N; }
If you really want to support the same on older compilers, there is a way, originally invented by Ivan Johnson, AFAIK:
#define COUNTOF(x) ( \
0 * sizeof( reinterpret_cast<const ::Bad_arg_to_COUNTOF*>(x) ) + \
0 * sizeof( ::Bad_arg_to_COUNTOF::check_type((x), &(x)) ) + \
sizeof(x) / sizeof((x)[0]) )
class Bad_arg_to_COUNTOF
{
public:
class Is_pointer;
class Is_array {};
template<typename T>
static Is_pointer check_type(const T*, const T* const*);
static Is_array check_type(const void*, const void*);
};
This uses sizeof(x)/sizeof(x[0]) to compute the size, just like the C macro does, so it gives a compile-time constant. The difference is that it first uses some template magic to cause a compile error if what you've passed isn't the name of an array. It does that by overloading check_type to return an incomplete type for a pointer, but a complete type for an array. Then (the really tricky part) it doesn't actually call that function at all -- it just takes the size of the type the function would return, which is zero for the overload that returns the complete type, but not allowed (forcing a compile error) for the incomplete type.
IMO, that's a pretty cool example of template meta programming -- though in all honesty, the result is kind of pointless. You really only need that size as a compile time constant if you're using arrays, which you should normally avoid in any case. Using std::vector, it's fine to supply the size at run-time (and resize the vector when/if needed).
Besides Carl's answer, the "standard" C++ way is not to use a C int array, but rather something like a C++ STL std::vector<int> list which you can query for list.size().
when u pass any array to some function. u are just passing it's starting address, so for it to work u have to pass it size also for it to work properly. it's the same reason why we pass argc with argv[] in command line arguement.
You can make a template function, and pass the array by reference to achieve this.
Here is my code snippet
template <typename TypeOfData>
void PrintArray(TypeOfData &arrayOfType);
int main()
{
char charArray[] = "my name is";
int intArray[] = { 1,2,3,4,5,6 };
double doubleArray[] = { 1.1,2.2,3.3 };
PrintArray(charArray);
PrintArray(intArray);
PrintArray(doubleArray);
}
template <typename TypeOfData>
void PrintArray(TypeOfData &arrayOfType)
{
int elementsCount = sizeof(arrayOfType) / sizeof(arrayOfType[0]);
for (int i = 0; i < elementsCount; i++)
{
cout << "Value in elements at position " << i + 1 << " is " << arrayOfType[i] << endl;
}
}
You have to use sizeof() function.
Code Snippet:
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int arr[] ={5, 3, 6, 7};
int size = sizeof(arr) / sizeof(arr[0]);
cout<<size<<endl;
return 0;
}
int arr1[] = {8, 15, 3, 7};
int n = sizeof(arr1)/sizeof(arr1[0]);
So basically sizeof(arr1) is giving the size of the object being pointed to, each element maybe occupying multiple bits so dividing by the number of bits per element (sizeof(arr1[0]) gives you the actual number of elements you're looking for, i.e. 4 in my example.
This method work when you are using a class: In this example you will receive a array, so the only method that worked for me was these one:
template <typename T, size_t n, size_t m>
Matrix& operator= (T (&a)[n][m])
{
int arows = n;
int acols = m;
p = new double*[arows];
for (register int r = 0; r < arows; r++)
{
p[r] = new double[acols];
for (register int c = 0; c < acols; c++)
{
p[r][c] = a[r][c]; //A[rows][columns]
}
}
https://www.geeksforgeeks.org/how-to-print-size-of-an-array-in-a-function-in-c/
Assuming you merely want to know the size of an array whose type you know (int) but whose size, obviously, you don't know, it is suitable to verify whether the array is empty, otherwise you will end up with a division by zero (causing a Float point exception).
int array_size(int array[]) {
if(sizeof(array) == 0) {
return 0;
}
return sizeof(array)/sizeof(array[0]);
}
If you want to know how much numbers the array have, you want to know the array length. The function sizeof(var) in C gives you the bytes in the computer memory. So if you know the memory the int occupy you can do like this:
int arraylength(int array[]) {
return sizeof(array) / sizeof(int); // Size of the Array divided by the int size
}