C++ compile-time expression as an array size - c++

I'm not sure if the term's actually "Array Addition".
I'm trying to understand what does the following line do:
int var[2 + 1] = {2, 1};
How is that different from int var[3]?
I've been using Java for several years, so I'd appreciate if explained using Java-friendly words.
Edit: Thousands of thanks to everyone who helped me out, Occam's Razor applies here.

It's not different. C++ allows expressions (even non-constant expressions) in the subscripts of array declarations (with some limitations; anything other than the initial subscript on a multi-dimensional array must be constant).
int var[]; // illegal
int var[] = {2,1}; // automatically sized to 2
int var[3] = {2,1}; // equivalent to {2,1,0}: anything not specified is zero
int var[3]; // however, with no initializer, nothing is initialized to zero
Perhaps the code you are reading writes 2 + 1 instead of 3 as a reminder that a trailing 0 is intentional.

It is any different from int var[3]. The compiler will evaluate 2 + 1 and replace it with 3 during compilation.

How is that different from int var[3]?
In no way that I can see.

It isn't any different; it is int var[3].
Someone might write their array like this when writing char arrays in order to add space for the terminating 0.
char four[4 + 1] = "1234";
It doesn't seem to make any sense working with an int array.

var[2 + 1] is not different from var[3]. The author probably wanted to emphasize that var array will hold 2 data items and a terminating zero.

This creates an array of 3 integers. You're right, there is no difference whether you express it as2 + 1 or 3, as long as the value is compile-time constant.
The right side of the = is an initializer list and it tells the compiler how to fill the array. The first value is 2, the second 1 and the third is 0 since no more values are specified.
The zero fill only happens when you use an initializer list. Otherwise there is no guarantee of that the array has any particular values.
I've seen this done with char arrays, to emphasize that one char is reserved for a string terminator, but never for an int array.

Related

1D dynamic array, parentheses

Let's say I have a 1D dynamic array, that I want to fill with fibonacci numbers.
User enters size as 15, so I want first 15 fibonacci numbers.
So my question is this:
int* arr = new int [size];
and this
int* arr = new int [size]{};
What do {} do ?, and what is the difference ?
Effectively the paranthesis version ensures that all values are initliazized (ints will be initialized to zero) while otherwise that array might be filled with memory garbage since it just gave you a memory block, not doing anything with it. As a result, the paranthesis version might be a tad slower but that will only matter if you call this very often or with megabyte large arrays.
Note that often in debug mode, you will get a clean array anyways.
More details:
Using (or not using) parentheses when initializing an array ( whetehr it's () or {} does not matter in this case as both can be used for initializing types or classes that have no custom constructor).

Assigning value to struct's field, change also other variable

Simple code
#include <iostream>
using namespace std;
struct foo {
int bar;
};
struct foo tab[2];
int sum = 0;
int main()
{
tab[2].bar = 3; //this change 'sum' value!
cout << sum << endl;
return 0;
}
result in 3 instead of 0. It is unbelievable, so problably I am missing something. What I have done wrong?
Arrays start at 0, so tab[2] would be the third element, but you only allocated 2 of them.
In this case, sum is in the memory directly after tab, so when you go to where the third tab would be, you're actually in the memory for sum.
Notice that you access tab[2] which is an overflow (its size is 2 so valid indices are 0 and 1).
So tab[2] accesses the memory address of sum.
When you declare your variable
struct foo tab[2];
tab[2] does not exist.
You can only do
tab[0].bar = 3
tab[1].bar = 3
because arrays index starts from 0 and ends at arraySize-1.
If you look closely tab has a length of 2. By accessing the index 2, you are accessing memory out of the tab, which means you are accessing sum.
This is the reason why you are changing sum.
First of all, turn on compiler warnings! If you'd allow the compiler to help you, then it would very likely point out the exact error in this line:
tab[2].bar = 3; //this change 'sum' value!
Depending on which compiler you use, the warning may be as follows:
warning: array subscript is above array bounds
struct foo tab[2]; has two elements with indices 0 and 1, you try access a non-existing 3rd element. This results in undefined behaviour of your program. Whatever results you got, it was just random. Your program could also randomly crash.
Note that your code is also half C and half C++. That's not good. You don't need to write struct foo when you want to refer to the foo type, it's enough to write foo. Instead of a raw array, std::array<Foo, 2> can be used. And using namespace std; should not be used by default.

How do I reinitialize a multidimensional array efficiently in Qt/C++?

In Qt, I have a 3-D int-array (say ID[x][y][z]) which I need to set back to 0 during computation.
Is there an efficient way to do it without using a loop?
I need the reinitialization because I am running a specific algorithm with a simple cost-function to get an estimation for the following more detailed computation, and I want to use the same data structure. Simply overwriting the array is not an option, because the algorithm reads and checks entries before writing them.
Sooner or later there's going to be a loop, but you can delegate it to another and more optimized function.
Also, if the "3D array" is really an array of arrays of arrays of some basic type (like int or char), then all the memory is contiguous so you can use a single function call to clear all of the memory in one single call.
Now which function to use; In C++ there are basically two functions you can use: The old C memset function, and the C++ std::fill function. Both should work fine, with proper casting and size, to set all of the data to a specific value.
Under the hood it will (almost) always be a loop. Don't worry, a loop without branches is quite efficient.
If you go for more readable, you can use a function like memset or std::fill which hides the loop.
Have a look at the answers to this question: What's the safe way to fill multidimensional array using std::fill?
The users #JoachimPileborg and #GeorgSchölly have already explained in their answers which functions can be used to reinitialize an array. However, I'd like to add some sample code and explain a difference between std::fill() and memset().
I assume that you want to (re)initialize your array with 0. In this case you can do it as shown in the following code:
#include <xutility> // For std::fill().
int main(int argc, char* argv[])
{
const int x = 2;
const int y = 3;
const int z = 5;
const int arraySize = x * y * z;
// Initialize array with 0.
int ID[x][y][z] = {};
// Use the array...
// Either reinitialize array with 0 using std::fill()...
std::fill(&ID[0][0][0], &ID[0][0][0] + arraySize, 0);
// ...or reinitialize array with 0 using memset().
memset(&ID[0][0][0], 0, sizeof(ID));
// Reuse the array...
return 0;
}
However, if you want to initialize your array with another value (for example, 1), then you have to be aware of a crucial difference between std::fill() and memset(): The function std::fill() sets each element of your array to the specified value. The function memset(), in contrast, sets each byte your array to the specified value. This is why memset() takes the array size as number of bytes (sizeof(ID)).
If you initialize your array with 0, this difference doesn't cause a problem.
But, if you want to initialize each element of your array with a non-zero value, then you have to use std::fill(), because memset() will yield the wrong result.
Let's assume you want to set all elements of your array to 1, then the following line of code will yield the expected result:
std::fill(&ID[0][0][0], &ID[0][0][0] + arraySize, 1);
However, if you use memset() in the following way, then you get a different result:
memset(&ID[0][0][0], 1, sizeof(ID));
As explained above, this line of code sets every byte to 1. Therefore, each integer element of your array will be set to 16843009, because this equals the hexadecimal value 0x01010101.

Difference Between *(Pointer + Index) and Pointer[]

int* myPointer = new int[100];
// ...
int firstValue = *(myPointer + 0);
int secondValue = myPointer[1];
Is there any functional difference between *(myPointer + index) and myPointer[index]? Which is considered better practice?
Functionally, they are identical.
Semantically, the pointer dereference says "Here's a thing, but I really care about the thing X spaces over", while the array access says "Here's a bunch of things, I care about the Xth one."
In most cases, I would prefer the array form.
There is no difference between
*(array+10); //and
array[10];
but guess what? since + is commutative
*(10 + array); //is all the same
10[array]; //! it's true try it !
No, they are functionally equivalent.
First, index is scaled up to the type size then added to the myPointer base, then the value is extracted from that memory location.
The "better practice" is the more readable one, which is usually, but not necessarily always, the myPointer[index] variant.
That's because you're usually interested in an element of the array, not the memory location to dereference.
There is no functional difference I know of but the form myPointer[1] is ultimately more readable and far less likely to incur coding errors.
DC
The form *(myPointer + 1) does not allow for changing the type of pointer to an object and therefore getting access to the overloaded [] operator.
Also debugging is far harder
int *ints[10];
int myint = ints[10];
is easier to pickup visually than
int *ints;
int myint = *(ints + 10);
also the compiler can insert range checking to catch the error at compile time.
DC
More readable and more maintainable code is better code.
As for functional part... There is no difference. Both times you are "playing with memory".
There is no functional difference. The decision to use either form is usually made depending on the context in which you are using it. Now in this example, the array form is simpler to use and read and hence is the obvious choice. However, suppose you were processing a character array, say, consuming the words in a sentence. Given a pointer to the array you might find it easier to use the second form as in the code snippet below:
int parse_line(char* line)
{
char* p = line;
while(*p)
{
// consume
p++;
}
...
}
Edit 1 : Decade-old question. But still, I think this answer will help to know the compiler's perspective.
Compiler creates the same machine code for both cases. here's a proof,
code 1
#include<stdio.h>
int main()
{
int myArr[5] = {1, 2, 3, 4, 5};
int value = myArr[0];
}
code 2
#include<stdio.h>
int main()
{
int myArr[5] = {1, 2, 3, 4, 5};
int value = *(myArr + 0);
}
Below is the result of the comparison done on assembly code generated by compiling the C code of both the codes with gcc -S.
Actually , When an Array 'a' is initialized a pointer to its first memory location ie.. a[0] is returned which is nothing but a ;
So if you do 'a+1' it is actually a pointer to a[1]
if you do 'a+2' it is actually a pointer to a[2]
if you do 'a+3' it is actually a pointer to a[3]
so on ,
so if you do *(a+1) you will get value of a[1] and similar for other values also.
if you do *(a) you actually get a[0],
So i think its pretty clear now how it works..

C++ arrays and size

If I have for example the following array declaration: int a[5];, this means that I have an array "a" that holds 5 integer variables.
Wouldn't it be in memory something like this (See the \0)?
|0|1|2|3|4|\0|
So, in this case, do I still say that a[] is of size 5 or should I say it is of size 6?
And, if I copy it to the array: int b[4] what will happen in this case? What will happen to the integer variable in location 4 of a[], will it overwrite \0?
Thanks.
Arrays are not, in general, automatically zero-terminated. C strings are zero-terminated, but this is not a C string.
There are only |0|1|2|3|4| in the memory, not the sixth one. So the size is 5.
Great explanation of arrays for beginners.