Why does this work?

Hi everyone,
Let me start with the code in question:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <iomanip>
using namespace std;

	void fill_AR ( int [], int, int, int, int );
	void printAR ( int [] );
	void print ( int [], int, int, int );

int main()
{

	int multiplier = 40;
	int inc= 725;
	int modulus = 729;
	int seed = 1;
	int newseed;
	int seed_new [10];
	
	fill_AR ( seed_new, seed, multiplier, inc, modulus );
	printAR ( seed_new );
	cout << "Run 1" << endl;
	print ( seed_new, multiplier, inc, modulus );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed,multiplier, inc, modulus );
	cout << "Run 2" << endl;
	print ( seed_new, multiplier, inc, modulus );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed, multiplier, inc, modulus );
	cout << "Run 3" << endl;
	print ( seed_new, multiplier, inc, modulus );
	
}

void fill_AR ( int AR [], int s, int mul, int incr, int mod )
{
	AR [0] = s;
	for ( int i = 0; i < 11; i++ )
	{
	AR[i+1] = (mul * AR[i] + incr) % mod;
	}	
}

void printAR ( int AR [] )
{
	for ( int cnt = 0; cnt < 10; cnt++ )
	{
	cout << AR[cnt] << "  " << endl;
	}	
}

void print ( int AR [], int mul, int incr, int mod )
{
	cout << endl << left << setw (12) << "Number" << setw (15) << "Multiplier" << setw (9)
	 	 << "Seed" << setw (15) << "Increment" << setw (11) << "Modulus"
		 << setw (10) << "Number Generated" << endl;

	for (int cnt = 1; cnt < 11; cnt++ )
	{
		cout  << left << setw (15) << cnt << setw (12) << mul << setw (10) << AR [cnt-1] << setw (15) 
		 	  << incr << setw (12) << mod << setw (10) << AR [cnt] << endl;
	}	
}
 


Now everytime I ran this code, the "multiplier, inc, and modulus" values were changing from the original values to different values - even though I didn't change them anywhere in the code.

Now when I fixed the code to make multiplier, inc, modulus CONSTANTS, it worked. Here is the code that worked:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <iomanip>
using namespace std;

	void fill_AR ( int [], int, int, int, int );
	void printAR ( int [] );
	void print ( int [], int, int, int );

int main()
{

	const int MULTIPLIER = 40;
	const int INC = 725;
	const int MODULUS = 729;
	int seed = 1;
	int newseed;
	int seed_new [10];
	
	fill_AR ( seed_new, seed, MULTIPLIER, INC, MODULUS );
	printAR ( seed_new );
	cout << "Run 1" << endl;
	print ( seed_new, MULTIPLIER, INC, MODULUS );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed, MULTIPLIER, INC, MODULUS );
	cout << "Run 2" << endl;
	print ( seed_new, MULTIPLIER, INC, MODULUS );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed, MULTIPLIER, INC, MODULUS );
	cout << "Run 3" << endl;
	print ( seed_new, MULTIPLIER, INC, MODULUS );
	
}

void fill_AR ( int AR [], int s, int mul, int incr, int mod )
{
	AR [0] = s;
	for ( int i = 0; i < 11; i++ )
	{
	AR[i+1] = (mul * AR[i] + incr) % mod;
	}	
}

void printAR ( int AR [] )
{
	for ( int cnt = 0; cnt < 10; cnt++ )
	{
	cout << AR[cnt] << "  " << endl;
	}	
}

void print ( int AR [], int mul, int incr, int mod )
{
	cout << endl << left << setw (12) << "Number" << setw (15) << "Multiplier" << setw (9)
	 	 << "Seed" << setw (15) << "Increment" << setw (11) << "Modulus"
		 << setw (10) << "Number Generated" << endl;

	for (int cnt = 1; cnt < 11; cnt++ )
	{
		cout  << left << setw (15) << cnt << setw (12) << mul << setw (10) << AR [cnt-1] << setw (15) 
		 	  << incr << setw (12) << mod << setw (10) << AR [cnt] << endl;
	}	
}


Now all my constants stayed the same.

MY QUESTION:: WHY IS THIS? The member functions never changed multiplier, inc and modulus, so how come adding the CONST all of sudden works?

Sorry this is long, hopefully someone can shed some insight though.
Your code has undefined behavior. You defined array as haveing 10 elements that have indexes from 0 to 9..

int seed_new [10];

but in function fill_AR

1
2
3
4
5
6
7
8
void fill_AR ( int AR [], int s, int mul, int incr, int mod )
{
	AR [0] = s;
	for ( int i = 0; i < 11; i++ )
	{
	AR[i+1] = (mul * AR[i] + incr) % mod;
	}	
}


you are overwriting memory that does not belong to the array that is you are trying access elements with indexes 10, 11, 12.

In the second case you defined the variables as const. They are npt ODR used so the compiler does not allocate memory for them. It simply uses their values.
memory corruption.

You are probably stepping out of bounds of your array and it's likely overwriting the memory of other variables. Declaring the other variables as const appears to solve the problem (even though it doesn't really) because it likely tells the compiler to store the variables elsewhere in memory (or not in memory at all -- as an optimization it might be removing them altogether).


I see at least 1 area where you are stepping outside of your array bounds:

1
2
3
4
5
6
7
8
9
10
11
12
13
void fill_AR ( int AR [], int s, int mul, int incr, int mod )
{
	// when you call this function, 'AR' points to a buffer [10] elements in size
	//    this means that [9] is the last legal element to access.  Any element higher
	//    than that would be 'BAD'

	AR [0] = s;
	for ( int i = 0; i < 11; i++ )   // loop stops at i=11... which means highest value for i
		// inside the loop is i=10
	{
	AR[i+1] = (mul * AR[i] + incr) % mod;   // writing to AR[i+1].  BAD
	}	
}


Note that since i=10 that means AR[i+1] is accessing AR[11] which is out of bounds, because the highest value you can access is AR[9]. This will corrupt memory causing weirdness similar to what you're seeing.


Be very very careful with array indexing and pointer dereferencing.
Last edited on
Thank you so much for your quick answer. Wow I didn't even think of that. But what did you mean by, "they are not ODR"? What does ODR mean please?

Just for the thread, I changed the size of the array and what I was trying to access and it worked. Here is the new code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <iomanip>
using namespace std;

	void fill_AR ( int [], int, int, int, int );
	void printAR ( int [] );
	void print ( int [], int, int, int );

int main()
{

	int multiplier = 40;
	int inc= 725;
	int modulus = 729;
	int seed = 1;
	int newseed;
	int seed_new [9];
	
	fill_AR ( seed_new, seed, multiplier, inc, modulus );
	printAR ( seed_new );
	cout << "Run 1" << endl;
	print ( seed_new, multiplier, inc, modulus );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed,multiplier, inc, modulus );
	cout << "Run 2" << endl;
	print ( seed_new, multiplier, inc, modulus );

	cout << "Enter a new seed number: ";
	cin >> newseed;

	fill_AR ( seed_new, newseed, multiplier, inc, modulus );
	cout << "Run 3" << endl;
	print ( seed_new, multiplier, inc, modulus );
	
}

void fill_AR ( int AR [], int s, int mul, int incr, int mod )
{
	AR [0] = s;
	for ( int i = 0; i < 9; i++ )
	{
	AR[i+1] = (mul * AR[i] + incr) % mod;
	}	
}

void printAR ( int AR [] )
{
	for ( int cnt = 0; cnt < 10; cnt++ )
	{
	cout << AR[cnt] << "  " << endl;
	}	
}

void print ( int AR [], int mul, int incr, int mod )
{
	cout << endl << left << setw (12) << "Number" << setw (15) << "Multiplier" << setw (9)
	 	 << "Seed" << setw (15) << "Increment" << setw (11) << "Modulus"
		 << setw (10) << "Number Generated" << endl;

	for (int cnt = 1; cnt < 11; cnt++ )
	{
		cout  << left << setw (15) << cnt << setw (12) << mul << setw (10) << AR [cnt-1] << setw (15) 
		 	  << incr << setw (12) << mod << setw (10) << AR [cnt] << endl;
	}	
}


Also, what did you mean by, "they are not ODR"? What does ODR mean please?
You still have the same problem:

1
2
3
4
5
6
int seed_new [9];  // <- declared as size 9, which means last legal index is [8]

//...  in printAR:
	for ( int cnt = 0; cnt < 10; cnt++ )
	{
	cout << AR[cnt] << "  " << endl;  // <-  accessing AR[9] -- OUT OF BOUNDS 
yes i do see this now, thank you. It's confusing because it still works, but I do see the problem in the code.
Once the array is in bounds in all places, do you think it's necessary to still use the CONST notation or not?
If you do not intent for the value to change, then use const
the array is irrelevant.
Topic archived. No new replies allowed.