Help initialising array in C++

In this forum members can discuss topics about specific programming languages.
Post Reply
Fogmeister
Posts: 27
Joined: Mon Aug 22, 2011 11:20 am

Help initialising array in C++

Post by Fogmeister »

Up to now I've got round this by doing the following if I want a bool array initialised to false...

Code: Select all

bool blah[1000];

for (int i = 0; i < 1000; i++)
    blah[i] = false;
but I am almost certain that there is a one line way of doing this but it just doesn't seem to work...

What I have tried is this...

Code: Select all

bool blah[10] = {true};

for (int i = 0; i < 10; i++)
if(blah[i])
    cout << i << " blah" << endl;
But I only get a single "blah" output for the value of i = 0.

Is there a different way of doing this?

TVM!
Image
User avatar
Argaen
Posts: 10
Joined: Fri Apr 10, 2009 11:19 pm

Re: Help initialising array in C++

Post by Argaen »

I forgot the details, but I remember (it's been long since I used C++) that the memset() function is meant for that, the documentation is here: http://www.cplusplus.com/reference/clib ... ng/memset/.
ImageEst Sularis Oth Mithas.
brainiac1530
Posts: 16
Joined: Sun Mar 02, 2014 2:32 pm

Re: Help initialising array in C++

Post by brainiac1530 »

Let me suggest some alternatives.

If you use std::array<bool,1000> Bools, you can use Bools.fill(true) to fill it with trues.
If you use std::bitset<1000> Bools, it does default-construct to zero. Use Bools.flip() to set them all to true. Small bitsets ( < 64 bits ) could be initialized with an integer value. Bitsets definitely only use one bit per bool (vice one byte).
If you use std::vector<bool> Bools(1000,true), it will be constructed with 1000 trues. It will also only occupy 1000 bits (probably, based on implementation, plus a small overhead of 20-30 bytes, again based on implementation). vector<bool> is extremely useful for sieves, as it has a small memory footprint, doesn't eat up stack space like bitset, and can be returned from a function efficiently with move-semantics.
User avatar
stephj
Posts: 5
Joined: Sun Apr 13, 2014 6:22 pm
Location: Lancashire, UK

Re: Help initialising array in C++

Post by stephj »

In C/C++ the value of an array variable is actually a pointer to its first element. i.e. blah[0], which explains why your second example of code only sets the first element.

To get it to set all ten elements, you would need to use:

Code: Select all

bool blah[10] = {true,true,true,true,true,true,true,true,true,true};
memset() will work but only if the compiler treats bool as an unsigned char (byte) with 0=false and 1=true.

If so, then:

Code: Select all

memset(blah,1,sizeof blah);
will work.
Image
JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 1:40 pm

Re: Help initialising array in C++

Post by JopieBK »

Okay, I know it's an old thread but it's still worth pointing out that the original post actually refers to two different things.

(a) Is there a better way of initialising a boolean array to false than using a for loop?
(b) Why does this only initialise only the first element to true?

Re (a), there is a better one-line way:

Code: Select all

bool blah[10] = {false}
This initialises the first array element to false. If you intialise one or more elements when declaring an array, the rest of the elements get default-initialised, which in the boolean case means to false.

Re (b):

Code: Select all

bool blah[10] = {true}
initialises the first element to true which results in the rest being default initialised to false, as found by the OP.

Code: Select all

bool blah[10]
normally results in random true/false values for each element.

So if you have to use an array of bool for some reason, all initialised to the same value, you must either set them all to true using a loop or use semantics where starting them out all as false makes sense.

stephj wrote:In C/C++ the value of an array variable is actually a pointer to its first element.
We all think that at some point, but it isn't, as demonstrated by trying to declare

Code: Select all

extern int* x
to refer to

Code: Select all

int x[]
and discovering that it won't work, or more typically by the error produced when trying to pass a 2D array x[][] to a function as **x : http://c-faq.com/aryptr/index.html
User avatar
ggoyo
Posts: 25
Joined: Sun Jun 22, 2014 10:45 am
Location: Paris
Contact:

Re: Help initialising array in C++

Post by ggoyo »

JopieBK wrote:
stephj wrote:In C/C++ the value of an array variable is actually a pointer to its first element.
We all think that at some point, but it isn't, as demonstrated by trying to declare

Code: Select all

extern int* x
to refer to

Code: Select all

int x[]
and discovering that it won't work, or more typically by the error produced when trying to pass a 2D array x[][] to a function as **x : http://c-faq.com/aryptr/index.html
It is actually true, an array is a pointer but the only difference is that it is constant, so you cannot do pointer arithmetic on it such as

Code: Select all

ptr++
or whatever that changes the adress.
You cannot pass it to a function as you pointed it out (no pun intended), what would happen if the function changes the adress to the first element ? If the function argument is (const **int x) then you can pass a 2D array to it, but cannot use pointer arithmetic inside that function.
Image
JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 1:40 pm

Re: Help initialising array in C++

Post by JopieBK »

ggoyo wrote:It is actually true, an array is a pointer but the only difference is that it is constant...
No, an array is not a pointer, constant or otherwise.
Saying that arrays and pointers are "equivalent" means neither that they are identical nor even interchangeable.
http://c-faq.com/aryptr/aryptrequiv.html
An array is an array and a pointer is a pointer, but in most cases array names are converted to pointers. A term often used is that they decay to pointers.
http://stackoverflow.com/questions/1641 ... inter-in-c
http://eli.thegreenplace.net/2009/10/21 ... lent-in-c/ gives more technical explanation with reference to some produced assembly.
ggoyo wrote:You cannot pass it to a function as you pointed it out (no pun intended), what would happen if the function changes the adress to the first element ? If the function argument is (const **int x) then you can pass a 2D array to it, but cannot use pointer arithmetic inside that function.
Firstly you can pass a 1D array to a function even without a const specifier but only because the compiler converts the array to a pointer, and it does this whether you declare the parameter as a pointer or as an array. If an array were already a pointer, constant or otherwise, then no conversion could happen. Additionally since the array is converted into a pointer then pointer arithmetic works within the function. The parameter is passed by value so no changes to the pointer within the function can affect the address of the external array. If you try the following code:

Code: Select all

#include <stdio.h>

int firstElement(int x[])
  {
  ++x;
  return x[0];  
  }
  
int main()
	{
	int x[3]= {1,2,3};
	
	printf("First element of the array = %d\n",firstElement(x));
	printf("First element of the array = %d\n",x[0]);
	
	return 0;
	}
you'll see that it compiles without warning and prints "First element of the array = 2" followed by "First element of the array = 1", demonstrating the above points. The code works identically if you declare "int firstElement(int* x)".

But what if we try something similar with a 2D array? If we use "int firstElement(int x[][]) the compiler bails out even if we also use the 'const'. If we try your 'const' solution and no pointer arithmetic...

Code: Select all

/* Arrays are not pointers */

#include <stdio.h>

int firstElement(const int** x)
	{
	return x[0][0];
	}

int main()
	{
	int x[2][3]= {
				 {1,2,3},
				 {4,5,6}
				 };
	
	printf("First element of the array = %d\n",firstElement(x));
	
	return 0;
	}
This compiles, but with the following warnings under gcc:

Code: Select all

warning: passing argument 1 of 'firstElement' from incompatible pointer type
note: expected 'const int **' but argument is of type 'int (*)[3]'
Because a 2D array is an array of arrays, it tries to convert it to a pointer to arrays but the function asks for a pointer to a pointer and so the compiler flags a warning.

If I try and run the program it fails on my machine with an access violation, indicating 'x' within the function hasn't been initialised to point to the beginning of the array.

You can't consider a 2D array as a pointer to pointers - constant or otherwise - because it's an array of arrays, and pointers and arrays are different. If you still have trouble understanding, consider that multidimensional arrays know their shape, yet how would an int** (whose value is purely an address) know where to find its element (1,1) in memory?
User avatar
ggoyo
Posts: 25
Joined: Sun Jun 22, 2014 10:45 am
Location: Paris
Contact:

Re: Help initialising array in C++

Post by ggoyo »

Say we have a 'Pointer' object in an object oriented language. We could define arrays as a subclass of Pointer and add a length field. In that sense, arrays are pointers.
Image
JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 1:40 pm

Re: Help initialising array in C++

Post by JopieBK »

In the sense of an unspecified OO language where 'Array' has been defined as a sub-class of a 'Pointer' object, yes an Array 'is a' Pointer, that's tautological.

In the sense of C/C++, arrays aren't pointers, and thinking they are is a common cause of errors.
User avatar
ggoyo
Posts: 25
Joined: Sun Jun 22, 2014 10:45 am
Location: Paris
Contact:

Re: Help initialising array in C++

Post by ggoyo »

JopieBK wrote: arrays aren't pointers, and thinking they are is a common cause of errors.
Please give me an example of error it can cause (not syntaxic of course), because I never had any.
JopieBK wrote:yet how would an int** (whose value is purely an address) know where to find its element (1,1) in memory?
If x is the adress of an int** then its (1,1) element is at the adress y+sizeof(int) where y is the value stored at the adress x+sizeof(int*) (usually sizeof(int) = sizeof(int*) = 4, but you never know). If a is the pointer then you can write a[1][1] or *(*(a+1)+1)
Last edited by ggoyo on Fri Aug 01, 2014 5:39 pm, edited 2 times in total.
Image
JopieBK
Posts: 6
Joined: Tue Jun 24, 2014 1:40 pm

Re: Help initialising array in C++

Post by JopieBK »

ggoyo wrote:Please give me an example of error it can cause (not syntaxic of course), because I never had any.
ggoyo wrote:If a is the pointer then you can write a[1][1]...

Code: Select all

#include <stdio.h>

int main()
	{
	int a[3][3] = {
				  {1,2,3},
				  {4,5,6},
				  {7,8,9}};
				  
	int* pointer_a = a;
	printf("%d\n",pointer_a[1][1]);
	
	return 0;
	}

Code: Select all

warning: initialization from incompatible pointer type [enabled by default]
int* pointer_a = a;
error: subscripted value is neither array nor pointer nor vector
pointer_a[1][1]
This isn't a matter for opinion or discussion. It's a fact. Arrays aren't pointers. The whole of http://c-faq.com/aryptr/index.html plus the other links provided explain that. I provided them because I thought it would help but you're clearly place more importance on trying to prove that you're not wrong. You're on your own there, I've no interest in clogging up these pages with ego arguments. Goodbye.
User avatar
ggoyo
Posts: 25
Joined: Sun Jun 22, 2014 10:45 am
Location: Paris
Contact:

Re: Help initialising array in C++

Post by ggoyo »

You declared pointer_a to be an (int*)... So when you do a[1] it does *(a+1), which dereferences the (int*) : at this point a[1] is an int (which is not a pointer type) so then when you do a[1][1] you are trying to dereference an int.

That has nothing to do with what I said, this is just you being dumb. You still did not provide any example.

If an array is not a pointer (by array we meant a 1d array, that was the initial post) why can I do

int[] a = {1};
int* p = a;

without any type of error?
Image
Post Reply