C++ What's wrong with my array/loop? - c++

I've just started learning C++ so I'm fairly sure the answer may be a simple one. As a test I'm just setting up an array and then wanting to print out the array by looping through it.
My code is below. It prints out my array as expected but then prints out a load of other numbers below it. What are these numbers and where are they coming from? I suspect that 'sizeof' isn't the best to use. All of the examples i've found are alot more complicated than I need. In any case I am interested to understand the extra numbers. Any insight available?
int age[4];
age[0]=23;
age[1]=34;
age[2]=65;
age[3]=74;
for (int i = 0; i <= sizeof(age); i++)
cout << age[i] << endl;
return 0;
...output:
23
34
65
74
4
2147307520
0
2293608
4198582
1
3084992
3085608
-1
2293592
1980179637
-725187705
-2

sizeof gives the size of an object in bytes. If the array elements are larger than one byte (as int usually is), the number will be larger than the array size.
One way to get the number of elements in an array is to divide by the size of an element:
for (size_t i = 0; i < sizeof(age)/sizeof(age[0]); i++)
std::cout << age[i] << '\n';
(note that you also need < rather than <=, or you'll still step off the end).
Another way is to pass a reference to the array to a function template, instantiated for the array size:
template <typename T, size_t size>
void print(T (&array)[size])
{
for (size_t i = 0; i < size; ++i)
std::cout << array[i] << '\n';
}
print(age);
Yet another way is to use a std::vector or std::array instead of a plain array:
std::array<int, 4> age;
age[0]=23;
age[1]=34;
age[2]=65;
age[3]=74;
for (size_t i = 0; i < age.size(); ++i)
std::cout << age[i] << '\n';

sizeof(age) == sizeof(int) * number_of_elements ==>
number_of_elements = sizeof(age) / sizeof(int)
Then your code becomes:
for (int i = 0; i < sizeof(age)/sizeof(age[0]); ++i)
cout << age[i] << endl;
In C++ you may write a function to calculate the size for you(doesn't work with dynamic arrays):
template <class T, std::size_t size>
std::size_t array_size( T(&arr)[size] )
{
return size;
}
If you are up to C++11, you could go with for-each loop:
for(int element : age){
....
}
Also, free-function form of std::begin and std::end can do the job:
for(auto b = std::begin(age); b != std::end(age); ++b){
....
}

Sould be i < 4 because sizeof(age) is 16 on a 32 bits machine.

sizeof(age) is the number of bytes of age, not the number of elements.
Divide it by the size of an element of age to get that:
for (int i = 0; i < sizeof(age) / sizeof(*age); i++)
cout << age[i] << endl;
Note: for dynamic arrays, you have to store the size of the array separately:
std::size_t size = 4; // size_t corresponds to maximum size an array can hold
int* age = new int[size];
for (int i = 0; i < size; i++)
cout << age[i] << endl;
The other numbers are garbage past the end of the array.
age[10] is undefined behavior, which is essentially garbage numbers.

Sizeof is age array is 16 bytes I.e. Sizeof(int) * 4. You need array length.

Since sizeof(age) returns 16, you have your 4 values plus 12 ones whose value comes from the memory that is right after your array. Values in those memory segment is random, depending on what has been stored there right before you launched your program. If you used a memory check tool, you would have had an error since this memory is probably not allocated for your program.
As the other ones said, you should probably giving the exact number of element in your array as an additional variable.
const int COUNT = 4;
int age[COUNT];
age[0]=23; age[1]=34; age[2]=65; age[3]=74;
for (int i = 0; i < COUNT; ++i)
{
cout << age[i] << endl;
}

Related

initializing a 2D array (Matrix) in C++

I am trying to create a 2D array by a for loop but I get some garbage random numbers
code:
unsigned int i, j;
int matrix[10][10];//={{},{}};
for (i = 0; i < sizeof(matrix[i])/sizeof(int); i++) {
for (j = 0; j < sizeof(matrix[j])/sizeof(int); j++) {
cout <<matrix[i][j] << " " << flush;
}
cout << endl;
}
and when I change cout part to the following
cout <<matrix[i][j] = {{i},{j}} << " " << flush;
I get an error.
how can I make it?
Thank you in advance.
The dimension of an array is how many indices are used to access it, which is different than the size of a dimension (how many elements are in a row of the dimension), which is different than the size of an array or the number of elements in the complete array.
With what you have written, you are writing a 2-dimensional array of 10 rows, each containing 10 elements for a total size of 100 elements.
If you want to do an initializer list in that syntax, you must specify each row and each element in nested braces. You have one top level set of braces for the total array, then a set of braces for each sub-array. You can do this with curly braces enclosing each row, specifying each element as a comma separated list:
unsigned int i, j;
int matrix[10][10] = {{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10},
{1,2,3,4,5,6,7,8,9,10}};
EDITED: The expression sizeof(matrix[i]) gives the size of the array as 40 because the compiler is able to figure that out at compile time, but it can be risky to rely on this since if you change it to a pointer to an array or the array is passed as a parameter to a function, it will give the size of the pointer instead of the array (as explained here: How do I determine the size of my array in C?). It would be better to display the array like this with the known length:
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
cout <<matrix[i][j] << " " << flush;
}
cout << endl;
}
Usually, for safety and convenience in changing, you can define the size using a macro like this:
#define ROWS 10
#define COLS 10
int matrix[ROWS][COLS] = ...;
then
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
cout <<matrix[i][j] << " " << flush;
}
cout << endl;
}
This way, if you decide to change the size of the matrix in the future, you only change the number in one place, the macro definition, instead of hunting through the code looking for each individual constant (especially with duplicate constants of 10, you might miss one or change an extra one that meant something else, which would cause problems somewhere else).

Why is the array size becoming so large?

I've been battling with figuring out how to pass a 2D array to a function and I think I've figured it out. My problem now though is for some reason this array (see below) is growing from 25 to 100 and I can't figure out why. I can't pinpoint where it's going haywire.
#include <iostream>
void testFunc(int (&n)[5][5]) {
n[0][0] = 5;
}
int main() {
int arr3[5][5];
// The array is initialized here with all values equaling 8.
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
arr3[i][j] = 8;
}
}
testFunc(arr3); // Function is called here changing [0][0] to the value 5.
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
std::cout << arr3[i][j] << ' ';
}
std::cout << '\n' << std::endl;
}
std::cout << sizeof(arr3) << std::endl;
return 0;
}
When I try to write the for-loop with i < sizeof(arr3) I get a size of 100. Not sure why. Where is it getting that value?
Your array size is 5*5 = 25, and int takes 4 bytes. so it becomes 100.
sizeofis not the number of elements. It's the size of the object in chars, that is, in bytes for most modern systems.
Your system has 32-bit (4 char/bytes) ints. Which gives you 5*5*4 = 100.
The size of data is also depend on size of CPU registers. In 32 bit machine the size of int is 4. However in earlier 16 bit machines the size of int is 2.

Storing array's of integers on the heap and accessing them via pointers

I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.

pointer arithmetic in C++ using char*

I'm having trouble understanding what the difference between these two code snippets is:
// out is of type char* of size N*D
// N, D are of type int
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
for (int j=0; j!=D; j++) {
out[i*D + j] = 5;
}
}
This code runs fine, even for very big data sets (N=100000, D=30000). From what I understand about pointer arithmetic, this should give the same result:
for (int i=0; i!=N; i++){
if (i % 1000 == 0){
std::cout << "i=" << i << std::endl;
}
char* out2 = &out[i*D];
for (int j=0; j!=D; j++) {
out2[j] = 5;
}
}
However, the latter does not work (it freezes at index 143886 - I think it segfaults, but I'm not 100% sure as I'm not used to developing on windows) for a very big data set and I'm afraid I'm missing something obvious about how pointer arithmetic works. Could it be related to advancing char*?
EDIT: We have now established that the problem was an overflow of the index (i.e. (i*D + j) >= 2^32), so using uint64_t instead of int32_t fixed the problem. What's still unclear to me is why the first above case would run through, while the other one segfaults.
N * D is 3e9; that doesn't fit in a 32 bit int.
When using N as size of array, why use int?
does a negative value of an array has any logical meaning?
what do you mean "doesn't work"?
just think of pointers as addresses in memory and not as 'objects'.
char*
void*
int*
are all pointers to memory addresses, and so are exactly the same, when are defined or passes into a function.
char * a;
int* b = (char*)a;
void* c = (void*)b;
a == b == c;
The difference is that when accessing a, a[i], the value that is retrieved is the next sizeof(*a) bytes from the address a.
And when using ++ to advance a pointer the address that the pointer is set to is advanced by
sizeof(pointer_type) bytes.
Example:
char* a = 1;
a++;
a is now 2.
((int*)a)++;
a is now 6.
Another thing:
char* a = 10;
char* b = a + 10;
&(a[10]) == b
because in the end
a[10] == *((char*)(a + 10))
so there should not be a problem with array sizes in your example, because the two examples are the same.
EDIT
Now note that there is not a negative memory address so accessing an array with a signed negative value will convert the value to positive.
int a = -5;
char* data;
data[a] == data[MAX_INT - 5]
For that reason it might be that (when using sign values as array sizes!) your two examples will actually not get the same result.
Version 1
for (int i=0; i!=N; i++) // i starts at 0 and increments until N. Note: If you ever skip N, it will loop forever. You should do < N or <= N instead
{
if (i % 1000 == 0) // if i is a multiple of 1000
{
std::cout << "i=" << i << std::endl; // print i
}
for (int j=0; j!=D; j++) // same as with i, only j is going to D (same problem, should be < or <=)
{
out[i*D + j] = 5; // this is a way of faking a 2D array by making a large 1D array and doing the math yourself to offset the placement
}
}
Version 2
for (int i=0; i!=N; i++) // same as before
{
if (i % 1000 == 0) // same as before
{
std::cout << "i=" << i << std::endl; // same as before
}
char* out2 = &out[i*D]; // store the location of out[i*D]
for (int j=0; j!=D; j++)
{
out2[j] = 5; // set out[i*D+j] = 5;
}
}
They are doing the same thing, but if out is not large enough, they will both behave in an undefined manner (and likely crash).

C++ 3d array - dynamic memory allocation aligned in one line

i have a quite weird question which probably has no practical use but the answers bothers me a lot. I tried to mess around today a little bit with arrays and how they are allocated in memory using this code: (Compiler Xcode 4 btw, 4 byte integer)
int ***c;
int size_x = 0;
int size_y = 0;
int size_z = 0;
cout << "Enter x: " << endl;
cin >> size_x;
cout << "Enter y: " << endl;
cin >> size_y;
cout << "Enter z: " << endl;
cin >> size_z;
c = new int**[size_x];
for (int i = 0; i < size_x; ++i) {
*(c+i) = new int*[size_y];
for (int j = 0; j < size_y; ++j) {
*(*(c+i)+j) = new int[size_z];
}
}
for (int i = 0; i < size_x; ++i) {
for (int j = 0; j < size_y; ++j) {
for (int k = 0; k < size_z; ++k) {
cout << (*(*(c+i)+j)+k) << endl;
//cout << &c[i][j][k] << endl;
}
}
}
delete [] c;
When i enter now: 3, 2 and 4 i get the following output in the console:
0x100100a60
0x100100a64
0x100100a68
0x100100a6c
0x100100a70
0x100100a74
0x100100a78
0x100100a7c
0x100100a90
0x100100a94
0x100100a98
0x100100a9c
0x100100aa0
0x100100aa4
0x100100aa8
0x100100aac
0x100100ac0
0x100100ac4
0x100100ac8
0x100100acc
0x100100ad0
0x100100ad4
0x100100ad8
0x100100adc
What my question is now, if we look at the output, than we see that mostly, the memory is aligned every 4 bytes but sometimes we see a bigger step like from 0x100100a7c to
0x100100a90 .
Is this normal and how can i prevent this? Why is this? Is there a possibility to force c to align my memory as a constant line? (I'm not native english so sorry for that but i don't know how to say it better)
Its just for general understanding :-)
Thank u!
P.S. is it enough to use delete [] once btw or do i have to go through each of the 3 memory blocks and delete [] there the whole array? EDIT:
I delete memory now like this and it works pretty good:
cout << "Free Memory" << endl;
for (int i = 0; i < m_sx; ++i) {
for (int j = 0; j < m_sy; ++j) {
delete [] m_array[i][j];
//delete [] (*(*(m_array)+j)+k);
}
delete [] m_array[i];
}
delete [] m_array, m_array = NULL;
Yes, this is normal. The memory is aligned, btw., it's just not contiguous because subsequent calls to new do not make this guarantee. And yes, you can allocate the entire 3-d array in a single, contiguous buffer:
int *A = new int[size_x * size_y * size_z];
or, safer
std::vector<int> A(size_x * size_y * size_z);
and then index it with
int element = A[i * size_z * size_y + j * size_z + k]
to get the element at (i,j,k).
This is, in fact, very useful, as it gives you multidimensional arrays with little overhead, preserving locality of reference and preventing indirection. Also, the error handling for this allocation scheme is much simpler so you run less of a risk of memory leaks. Any good matrix library will be implemented this way. For C++, that includes Boost.MultiArray.
As for deallocation: yes, you need multiple calls to delete[] in your present scheme.
Heres a routine which allocates the 3D array of dimension N1 x N2 x N3 in contiguous memory space while allowing you the a[i][j][k] syntax for operator access. The array is dynamic but continuous so it's a huge plus over the vector<> approach and loops of new[] calls.
template <class T> T ***Create3D(int N1, int N2, int N3)
{
T *** array = new T ** [N1];
array[0] = new T * [N1*N2];
array[0][0] = new T [N1*N2*N3];
int i,j,k;
for( i = 0; i < N1; i++) {
if (i < N1 -1 ) {
array[0][(i+1)*N2] = &(array[0][0][(i+1)*N3*N2]);
array[i+1] = &(array[0][(i+1)*N2]);
}
for( j = 0; j < N2; j++) {
if (j > 0) array[i][j] = array[i][j-1] + N3;
}
}
cout << endl;
return array;
};
template <class T> void Delete3D(T ***array) {
delete[] array[0][0];
delete[] array[0];
delete[] array;
};
And later in your implementation routine...
int *** array3d;
int N1=4, N2=3, N3=2;
int elementNumber = 0;
array3d = Create3D<int>(N1,N2,N3);
cout << "{" << endl;
for (i=0; i<N1; i++) {
cout << "{";
for (j=0; j<N2; j++) {
cout << "{";
for (k=0; k<N3; k++) {
array3d[i][j][k] = elementNumber++;
cout << setw(4) << array3d[i][j][k] << " ";
}
cout << "}";
}
cout << "}";
cout << endl ;
}
cout << "}" << endl;
Delete3D(array3d);
Gives the output:
{
{{ 0 1 }{ 2 3 }{ 4 5 }}
{{ 6 7 }{ 8 9 }{ 10 11 }}
{{ 12 13 }{ 14 15 }{ 16 17 }}
{{ 18 19 }{ 20 21 }{ 22 23 }}
}
Since this is tagged C, here is also a C answer. Since C99 multidimensional arrays can be handled quite efficiently, even if the sizes are dynamic:
double c[size_x][size_y][size_z];
This allocates the matrix contiguously on the stack. Matrix elements are accessed by c[i][j][k] and the compiler does all the indexing arithmetic for you. If you fear that this could lead to SO, you can easily call malloc with it:
double (*c)[size_y][size_z] = malloc(sizeof(double[size_x][size_y][size_z]));
The issue is not that your memory isn't aligned ... the requirement by the C++ specification for a call to new and new[] is that it passes back a pointer pointing to contiguous memory that is properly aligned for the platform and the size of the object requested.
Your problem is that you are not allocating the entire buffer for the array with a single call to new[], but rather with multiple calls to new[]. Therefore while each call to new will return aligned and contiguous memory, the multiple calls to new[] are not required to return memory buffers that themselves are contiguously allocated. For example, each call to new[] returns aligned memory, but as you noted, there can be "gaps" in the start of each memory array that new returns. The reason for these "gaps" can have multiple reasons, and really depends on how the underlying OS is allocating memory for your program.
If you do not want to have any "gaps" in each array, then you will need to allocate the entire buffer with a single call to new.
Finally, to answer your question about delete[], yes, because you did not allocate the entire memory buffer with a single call to new[], you cannot delete your array with a single call to delete[]. Every call to new[] must be paired with a call to delete[] since those were separate memory allocations.
Yes this is normal.
You allocate data row by row; The only thing you can be sure is that data will be contiguous on each row.