Strange array initialization (porting from C to C++) [duplicate] - c++

What is the meaning of following Code? Code is from the regression test suite of GCC.
static char * name[] = {
[0x80000000] = "bar"
};

In C99 you can specify the array indices to assigned value, For example:
static char * name[] = {
[3] = "bar"
};
is same as:
static char * name[] = { NULL, NULL, NULL, "bar"};
The size of array is four. Check an example code working at ideaone. In your code array size is 0x80000001 (its an hexadecimal number).
Note: Uninitialized elements initialized with 0.
5.20 Designated Initializers:
In ISO C99 you can give the elements in any order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in C89 mode as well. This extension is not implemented in GNU C++.
To specify an array index, write [index] = before the element value. For example,
int a[6] = { [4] = 29, [2] = 15 };
is equivalent to
int a[6] = { 0, 0, 15, 0, 29, 0 };
One more interesting declaration is possible in a GNU extension:
An alternative syntax for this which has been obsolete since GCC 2.5 but GCC still accepts is to write [index] before the element value, with no =.
To initialize a range of elements to the same value, write [first ... last] = value. For example,
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
Note: that the length of the array is the highest value specified plus one.
Additionally, we can combine this technique of naming elements with ordinary C initialization of successive elements. Each initializer element that does not have a designator applies to the next consecutive element of the array or structure. For example:
int a[6] = { [1] = v1, v2, [4] = v4 };
is equivalent to
int a[6] = { 0, v1, v2, 0, v4, 0 };
Labeling the elements of an array initializer is especially useful when the indices are characters or belong to an enum type. For example:
int whitespace[256] = { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1
};

It's called designated initializer which is introduced in C99, gcc also supports it in GNU89 as an extension, see here for detail.
int a[6] = { [4] = 29, [2] = 15 };
is equivalent to
int a[6] = { 0, 0, 15, 0, 29, 0 };

It's a C99 designated initializer. the value in brackets specifies the index to receive the value.

Related

Calculating an array's number of elements... Able to refer to its index values by just stating the return type? What? How? Why? (C++)

I am learning how to calculate the size and number of elements in an array and came across a question. In a tutorial I see
we can calculate the number of elements in an array as follows ...
int array_variable [] = {1, 5, 8, 10};
int array_variable_number_of_elements = sizeof(array_variable) / sizeof (int);
I am aware and fully understand why you could replace
sizeof (int);
with
sizeof (array_variable[0]); // or use any index value from the array_variable
The video appears to suggest using just int is good practice which I don't understand. The computer obviously isn't psychic and int is simply a data type. What happens when there are two int type arrays in the same function? Why does this work? Does this work because it is in the same line as the following?
int array_variable_number_of_elements = sizeof(array_variable)
Thanks :)
Second approach is better and more generic, when you need to change the type of array int to char, you don't have to edit second line at all.
char array_variable [] = {'a', 'b', 'c' }; //changed this line only
int array_variable_number_of_elements = sizeof(array_variable) / sizeof
(array_variable[0]);
To answer your below comment;
above lines you can interpret like below;
int array_variable = {1, 2, 3, 4, 5 };
int array_variable_number_of_elements = sizeof(array_variable) / sizeof ( int);
// ^^^^^^^^^ ^^^^ ^^^
// array_variable_number_of_elements = 20 / 4 ; // 20 / 4 = 5
total array size in bytes 20 and size of int is 4 bytes in my system;
total number of elements in array is 5;

which is best way to initialize array, "memset" or " {//value} "?

int main(){
int ar[50]={1};
//OR
int br[50];
memset(br, 1, sizeof(br));
return 0;
}
int ar[50]={1};
This will set only the first element to 1. Rest all will be 0.
memset(br, 1, sizeof(br));
This will set all the bytes in br to 1. It is not the same as setting all the values to 1. The values afterwards are:
{16843009, 16843009, 16843009, 16843009, 16843009}
Use memset when you know you really need it. It is not exactly made for initializing arrays, it just set the memory to a particular value.
Best way in C++? Use std::fill or std::fill_n.
Example:
int array[5];
std::fill(array, array + 5, 8);
Array now contains:
{8, 8, 8, 8, 8}
Using fill_n
std::fill_n(array, 5, 99);
Array now contains:
{99, 99, 99, 99, 99}
As a side note, prefer using std::array instead of c-style arrays.
Try on godbolt: https://godbolt.org/z/DmgTGE
References:
[1] : Array Initialization
[2] : memset doc
suppose you do
int ar[50] = {-1};
Now you will expect this line to initialize all array elements with -1
but it will not. It will only set the first element of array to -1 and rest to 0.
Whereas memset will show the expected behaviour.
See this Initialization of all elements of an array to one default value in C++? for more info.
let's take an example:-
int arr[5] = { 1, 2 }; // this will initialize to 1,2,0,0,0
int ar[5] = { }; // this will initialize all elements 0
int myArray[10] = {}; // his will also all elements 0 in C++ not in c
So If you want to initialize a specific value to an array use memset().
If you want to initialize all elements in an array to 0 use
static int myArray[10]; // all elements 0
Because objects with static storage duration will initialize to 0 if no initializer is specified and it is more portable than memset().
Also, The int ar[50]={0}; will be infinite because it just initializes the array and does not have an ending but in memset(arr,0,sizeof(br)) it has the correct way of ending the loop in arrays

Copy section of an array into a std::vector in C++

Hello im wondering if its possible to copy a section of an array whilst initializing a vector.
For example I have tried
UINT16 myarray[] = { 0,1,2,3,4,5,6, ..., n };
std::vector<UINT16> myvect(myarray[3], myarray[3] + 16);
This kind of works however I seem to get more data than i intended. Is this the correct usage?
The way is to pass iterators, not values
std::vector<UINT16> myvect(myarray + 3, myarray + 3 + 16);
UINT16 myarray[] = { 0,1,2,3,4,5,6, ..., n };
std::vector<UINT16> myvect(myarray[3], myarray[3] + 16);
This uses myarray[3] which is 3 and myarray[3] + 16 which is 19 as arguments to the myvect constructor. Which in turn sets up myvect to contain 3 elements, all with the value 19.
If you want a copy of the 16 elements starting at index 3, you can do it like this:
std::vector<UINT16> myvect(&myarray[3], &myarray[3 + 16]);
Here is a different (more verbose) way:
uint16_t myarray[] = { 0, 1, 2, 3, 4, 5, 6, ..., n };
constexpr auto arr_size = sizeof(myarray) / sizeof(myarray[0]);
constexpr auto copy_start = std::min< size_t >(3, arr_size);
constexpr auto copy_count = 19;
constexpr auto copy_end = std::min< size_t >(copy_start + copy_count, arr_size);
vector< uint16_t > myvect(std::next(myarray, copy_start), std::next(myarray, copy_end));
Instead of UINT16 you can use uint16_t type from C++11 onwards: Fixed width integers (if your compiler supports it)
If your values are available at compile time, then you can use compile time constants(constexpr) to calculate the helper variables. Otherwise const should be used.
Standard algorithms can be used also on arrays so providing an offset to std::next can be used to get the n-th element of an array.

C++ casting static two-dimensional double array to double**

I have such matrix in my program:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
And I'd like to cast it to double** type.
I've already tried simple double** a = (double**)m;, but it doesn't work (when I try to read any value, I get "Access violation reading location 0x00000000.", which means I'm trying to read from NULL adress.
I found almost working solution:
double *b = &m[0][0];
double **c = &b;
It works when I read field c[0][any]
But same NULL adress reading problem occurs, when I try to read value from field c[1][0].
What is the proper way to cast my double m[3][4] array to type double**?
edit:
You say that's impossible. So I'll change a problem a little bit. How can I pass two-dimensional double array as a parameter to a function? My function has prototype:
void calculate(double **matrix, int n); //where matrix size is always n by n+1
And it's working fine with dynamically-allocated arrays. I doubt that only way to make it work is allocating new dynamical array and copy original static array one element by another...
You can't.
The notation double** refers to an array of pointers. You don't have an array of pointers, you have an array of arrays of doubles.
You can't just cast the array. You are going to have to create something like this:
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
double *marray[3] = {m[0],m[1],m[2]};
calculate(marray,3);
Or you can use a loop:
const size_t n = 3;
double *marray[n];
for (size_t i=0; i!=n; ++i) {
marray[i] = m[i];
}
calculate(marray,n);
When you write
double m[3][4]
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
The compiler actually creates an array of doubles as if you had written
double _m[] = {2, 4, 5, 7, 4, 5, 1, 12, 9, 12, 13, -4};
However, thanks to C/C++ type system, the compiler remembers that m's type
is double [3][4]. In particular it remembers the sizes 3 and 4.
When you write
m[i][j]
the compiler replaces it by
_m[i * 4 + j];
(The 4 comes from the second size in double [3][4].) For instance,
m[1][2] == 1 and _m[1 * 4 + 2] == _m[6] == 1 as well.
As others said, a double** is a different type which doesn't carry the
sizes with it. To consider double** a as a 3 x 4 matrix, a[0], a[1] and
a[2] must be pointers to double (that is, double*) pointing to the
first element of the corresponding row. You can achieve this with
double* rows[] = { &m[0][0], &m[1][0], &m[2][0] };
double** a = &rows[0];
A simple cast doesn't create the variable rows above. Let me present other
alternative (but equivalent) ways to define rows
double* rows[] = { &m[0][0], &m[0][0] + 4, &m[0][0] + 2 * 4};
double* rows[] = { &_m[0], &_m[4], &_m[2 * 4]};
As you can see, only the second size (i.e. 4) is necessary. In general, for
multi-dimensional arrays, all sizes but the first are required. For this
reason a 1-dimensional array
double x[4] = { 1, 2, 3, 4 };
can be implicitly converted to a double*
double* y = x;
Using this fact we can also write
double* rows[] = { _m, _m + 4, _m + 2 * 4};
Indeed, _m is converted to a double* pointing to m[0]. Then, in _m + 4,
_m is is converted to a double* pointing to m[0] and to this pointer
it's added 4. Hence, _m + 4 is a pointer the fourth double following
_m[0], which is _m[4] and so on.
So far I have explained why you cannot cast a double [3][4] (or any other sizes) to a double**. Now, I'shall show, in your particular case, how calculate can be defined.
template <int N>
void calculate(double (&m)[N][N+1]) {
// use m as a double[N][N+1]
}
You call
calculate(m);
and the compiler will deduce the size N for you. In general (i.e, when the second dimension is not the N + 1) you can write
template <int N, int M>
void calculate(double (&m)[N][M]) {
// use m as a double[N][M]
}
If you're always using arrays (no pointers) for initialization, and you are able to avoid the pointer stuff in your calculate function, you might consider the following option, which uses size deduction by templates.
template<int m, int n>
void doubleFunc(double (&mat)[m][n])
{
for (auto i = 0; i < m; i++)
{
for (auto j = 0; j < n; j++)
{
std::cout << mat[i][j] << std::endl;
}
}
}
It worked during my quick test.
double m[3][4] =
{
{2, 4, 5, 7},
{4, 5, 1, 12},
{9, 12, 13, -4}
};
doubleFunc(m);
You can pass a 2d array as a function parameter:
void calculate(double matrix[][y], int n);
Until variable-length arrays are in the C++ standard, your choices include:
If your compiler supports variable-length arrays as an extension, you can likely pass them with a function declaration such as void foo(std::size_t n, double a[][n+1]). Note that the compiler likely requires n to be passed before a parameter declaration that uses n or requires some special syntax.
You can pass a double * and do index arithmetic manually in the function: void foo(std::size_t n, double *a) { … a[row*(n+1) + column] … }
You can create a class the implements variable-length arrays by doing the index arithmetic in its accessor functions.
You can allocate space for n pointers to double, fill those pointers with pointers to each row of the array, and pass the address of the space.

Initializing arrays in C++

I'm trying to initialize the last element in the array
int grades[10];
to grade 7 but it doesn't seem to work
I'm using C++ btw
If you want to initialize them all at definition:
int grades[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 7 };
If you want to initialize after:
int grades[10];
grades[9] = 7;
But, be aware that grades 0..8 will still be uninitialized, and will likely be junk values.
One more thing, if you initialize only the first element (if explicit array size is specified) or a shorter initiliazation list, the unspecified elements are fill with 0. E.g.
int grades[10] = {8}; //init with one element
is the same as:
int grades[10] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
or
int grades[10] = { 1, 9, 6, 16 }; //or init with a shorter than array size list with a minimum of 1 element
is the same as:
int grades[10] = { 1, 9, 6, 16, 0, 0, 0, 0, 0, 0 };
I find it handy for initializing an array with 0 values.
float coefficients[10] = {0.0f}; //everything here is full of 0.0f
when You write something like
int a[5] = {0};
it sets the whole array to zero on the contrary
int a[5] = {3};
sets only the first element and the rest may be anything(garbage values);
if You want to set the whole array with some value then u can go for the
std :: fill()
something like this
std::fill(arr, arr+100, 7); // sets every value in the array to 7
and if there is a character array You can always go for the memset function
The last element is grades[9], since arrays in C++ are zero-based (e.g. grades[0] to grades[9] are 10 elements). Is that what you're doing?
You might need to subtract one from the grade to use as your subscript value, or set the extent to one more.
Remember that an array with ten elements will have grades[0] through grades[9], and that grades[10] is an error.