# Thread: cellular autonoma "edge effects"

1. ## cellular autonoma "edge effects"

Alrighty, I've built a simple ascii model of a cellular autonoma:

Code:
```int cells[50][50];

int main()
{

cells[0][24]=1;

for(int a=1;a<50;a++)
{
for(int b=0;b<50;b++)
{
if( ((cells[a-1][b-1])==1) || ((cells[a-1][b+1])==1) ) cells[a][b]=1;
}
}

for(a=0;a<50;a++)
{
for(int b=0;b<50;b++)
{
if(cells[a][b]) cout << (char)31;
else cout << (char)0;
}
cout << endl;
}

cin.get();

}```
as you can see, each element checks to see if either the one above it or the one below is has a value of 1. if either one does, it is assigned the value of 1.

when it gets to the edge, for some reason the edge elements are assigned values of 1, even though no element above them is true.
the edge ones check for elements that technically don't exist, but those nonexistant elements should still be false...

any ideas?

if i change it to this it works:

Code:
`int cells[50][51];`
thanks a lot for the help

2. I think the problem is that you are indexing outside of the array in your first set of for loops.

You do this:

for(int a=1;a<50;a++)
{
for(int b=0;b<50;b++)
{
if( ((cells[a-1][b-1])==1) ||
((cells[a-1][b+1])==1) ) cells[a][b]=1;
}
}

But assume now that you get to the last entry of a row, i.e.
if (cells[0][49-1] == 1) || (cells[0][49+1]==1) cells[0][49] = 1;

But it turns out that there is no entry cells[0][50], because you didn't actually allocate space for it.

Even worse, think about the first row entry:

if (cells[0][0-1] == 1 || cells[0][0+1] == 1) cells[0][0] = 1;

So in this case you are indexing cells[0][-1]? Actually the -1 will probably turn into the largest possible unsigned integer, which is way, way out of bounds for your array.

So you might want to consider declaring
int cells[50][52];

and change the logic in the for loop appropriately.

3. yes, i am aware that the for loop is attempting to access elements of the array that are undefined.

However, these attempts to access the array, although technically not correct, are allowed by my compiler. For example, calls to cells[0][99], although way outside of bounds, will still return 0. So the elements that are dependent on these "out of bounds" calls should still function... but they dont...

consider the elements on the edges, but the ones that are at the top of the array. they are checking values that are out of bounds, but they still function correctly.

4. Undefined behvior does not mean error, an error is well defined. Undefined behavior includes working correctly, for whatever you expect correct to be. It's just not consistant and can also include any other behavior imagineable. The two most common effects of accessing beyond the bounds of an array are accessing within the bounds of some other variable or accessing unassigned memory. This memory could be assigned later and it's values are arbitrary. Another common effect is to change the return address, changeing return; into an arbitrary goto. None of these things are guarenteed, and can change at any time, unless you wanted it to change, then it won't. Undefined behavior, just say no kids.

C and C++ does exactly what you tell it to do, and it spends the absolute minimum effort trying to figrue out if what you are asking for makes a bit of sence. This leads to a very lean, lightweight language, but it puts tremendous responsibilty on the programmer. If you want formal methods and lot's of safety features use Ada. C provides a high level assembly languge, C++ adds a bunch of cool gadgets to C.

5. ## What!!!!

i read the conversation about 3 times and i cant understand what it is this program is trying to accomplish. Maybe one of you can shed some light for me?

6. With a few changes, it looks semi-interesting when printed out...it's not going to solve integrals or anything if that's what you're wondering.

7. Originally Posted by krygen
yes, i am aware that the for loop is attempting to access elements of the array that are undefined.

However, these attempts to access the array, although technically not correct, are allowed by my compiler. For example, calls to cells[0][99], although way outside of bounds, will still return 0. So the elements that are dependent on these "out of bounds" calls should still function... but they dont...

consider the elements on the edges, but the ones that are at the top of the array. they are checking values that are out of bounds, but they still function correctly.
But it's not right. (Proved by your admission that it doesn't give the right answer in its original form.)

For example the address of cells[24][-1] is equal to the address of cells[23][49]. This is not out of the range of addresses of the array, but also does not give the correct solution to your problem! As the beginning of each row, you sometimes are looking at a 1 stored at the end of the previous row.

Other than cells[0][-1], your references to elements of the cells[][] array are completely defined, and predictable and repeatable (and obviously not what you had in mind).

try this:
Code:
```#include <iostream>
using namespace std;

int cells[50][50];

int main()
{
int a, b;
//int cells[50][50];// = {0};

cells[0][24]=1;

cout << "Address of cells[23][49] = " << (void *)&cells[23][49] << endl;
cout << "Address of cells[24][-1] = " << (void *)&cells[24][-1] << endl;

// First test for all zeros in the array (except for the one we set to 1)
cout << "begin test" << endl;
for (a = 0; a < 50; a++) {
for (b = 0; b < 50; b++) {
if (cells[a][b]) {
cout << "cells[" << a << "][" << b << "] = " << cells[a][b] << endl;
}
}
}
cout << "end   test" << endl << endl ;

// Now store some things "out of range" (not really out of range)
for (a = 1; a < 50; a++) {
cells[a][-1] = 1;
cells[a][50] = 1;
}

// Now test for alteration of array elements with "normal" addressing
cout << "begin test2" << endl;
for (a = 0; a < 50; a++) {
for (b = 0; b < 50; b++) {
if (cells[a][b]) {
cout << "cells[" << a << "][" << b << "] = " << cells[a][b] << endl;
}
}
}
cout << "end   test2" << endl;

return 0;
}```

8. i understand now. thanks everybody + dave evans u were esp. helpful