Problem with modifying array argument in function

Hello everyone!
I've got some experience with Java and C, but I'm very new to C++. Therefore, I guess the answer to my question will be obvious, but I just can't figure it out on my own.

I've got the following 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
#include <gmp.h>
#include <flint.h>
#include <fmpz.h>
#include <fmpz_poly.h>
#include <iostream>

using namespace std;

template<int length>

void random_code(fmpz_t (&result)[length]) {
	for(int i=0; i<length; i++) {
		fmpz_set_ui(result[i], 1); //not quite random, but for now it will do
	}
}

int main() {
	int len = 4;
	fmpz_t test[len];
	for(int i=0; i<len; i++) {
		fmpz_init(test[i]);
	}
	random_code(test);
	cout << "value of test: ";
	for(int i=0; i<len; i++) {
		fmpz_print(test[i]);
	}
	cout << endl;

	return 0;
}


I want to initialize an array of fmpz_t's and then set each component in the array to a certain value. The problem is that I want to modify the array argument in random_code, so I made the argument a reference to that array, but it doesn't seem to work.

When I try to compile it, I get the following error and notes:

gen_code.cpp: In function 'int main()':
gen_code.cpp:23:18: error: no matching function for call to 'random_code(fmpz [len][1])'
random_code(test);

gen_code.cpp:11:6 note: candidate: template<int length> void random_code(fmpz (&)[length][1])
void random_code(fmpz_t (&result)[length]) {

gen_code.cpp:11:6: note: template argument deduction/substitution failed:
gen_code.cpp:23:18: note: variable-sized array type 'int' is not a valid template argument
random_code(test);

I know that there is something wrong with the line 'random_code(test)' in main() and that I don't call the argument correctly, but I just don't see the solution, so I hope there's someone who can help me. Thanks in advance!
I just threw this together to get it to compile and run.
The typedef was just a temporary workaround, you don't need that.
Note len in main() must be const.

The function bodies at lines 7, 8 and 9 are just random nonsense I made up, again to get it to compile and link.

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
#include <iostream>

using namespace std;

typedef int fmpz_t;

void fmpz_set_ui(fmpz_t & a, int b ) { a = b; }
void fmpz_init(fmpz_t & a) { a = 0; }
void fmpz_print(fmpz_t a) { std::cout << a << ' '; }

void random_code(fmpz_t result[], int length) {
    for(int i=0; i<length; i++) {
        fmpz_set_ui(result[i], 1); //not quite random, but for now it will do
    }
}

int main() 
{
    const int len = 4;
    fmpz_t test[len];
	
    for (int i=0; i<len; i++) {
        fmpz_init(test[i]);
    }
	
    random_code(test, len);
	
    cout << "value of test: ";
    for (int i=0; i<len; i++) {
        fmpz_print(test[i]);
    }
    cout << endl;

    return 0;
}
Last edited on
Thanks a lot, it works!! But I'm a bit confused now, because I searched on Google and I learned that when you want to modify an argument of a function inside the body of that function, you should put the reference to that argument in the function (i.e. & before the argument). But now you didn't and it still works. Could you perhaps explain me that?
My code does use references in
7
8
void fmpz_set_ui(fmpz_t & a, int b ) { a = b; }
void fmpz_init(fmpz_t & a) { a = 0; }


At line 11,
 
void random_code(fmpz_t result[], int length) {

When an array is passed as a parameter to a function, it actually passes the address of the first element of the array. See "Arrays as parameters" in the tutorial.
http://www.cplusplus.com/doc/tutorial/arrays/
Thanks for your answer! But the library fmpz doesn't use references in those functions, unlike your implementation of the functions.
Well, I had no idea what the functions fmpz_set_ui() and fmpz_init() were supposed to do, I've no idea what type of animal a fmpz represents. I just wrote some code which would compile and run, that's all.

edit:
A bit of googling, it looks like type fmpz_t is actually a typdef of a pointer type, thus it uses a pointer rather than a reference.
Last edited on
Thanks for your help!! I've got one last question. I'm not completely comfortable with pointers and references yet, especially not in the case of arrays. Does the fact that fmpz_t uses a pointer rather than a reference mean that I have to change anything to the code? The function random_code now looks like this:

 
void random_code(fmpz_t result[], size_t length) {


I mean, it works, but as I learned to use references when modifying an argument in a function, I'm still a bit confused.
I would think your code is fine as it stands now,

Pointers and references are loosely related. They are not the same thing. But both of them allow a function to change the contents of a parameter.

Consider the following example. I tried to keep it as simple as possible.

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
#include <iostream>

using namespace std;

void changex(int x)
{
    x = x + 1;
}

void changey(int* y)
{
    *y = *y + 1;
}

void changez(int &z)
{
    z = z + 1;
}

int main()
{
    int x = 5;
    int y = 5;
    int z = 5;

    changex(x);    // x is passed by value
    changey(&y);   // address of y is passed
    changez(z);    // z is passed by reference

    cout << "x: " << x << "    y: " << y << "    z: " << z << '\n';
  
    return 0;
}

x: 5    y: 6    z: 6


1. changex(int x) This example fails to work. Depending on the compiler, there may be a warning message, mine gives 'x' is assigned a value that is never used at line 7. The variable x is a local variable which exists only for the lifetime of the function. Its value is a copy of the parameter given when the function is called

2. changey(int* y) y is a pointer. When the function is called, the parameter must be a pointer. Notice also within the function the pointer must be dereferenced to access the thing which is pointed to.

3. changez(int &z) Often this is the preferred approach. z is passed by reference. This means that in effect the variable z inside the function is the same object as that in the calling code (though it need not have the same name).
As for arrays and pointers, when passing an array to a function, it is the address of the array start which is passed, and though an array is not the same thing as a pointer, they have similarities:
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
#include <iostream>

using namespace std;

void func1(char * str)
{
    *str = 'L';
}

void func2(char str[])
{
    str[0] = 'B';
}

int main()
{
    char word1[] = "dog";
    char word2[] = "cat";

    func1(word1);
    func2(word2);

    cout << "word1: " << word1 << '\n';
    cout << "word2: " << word2 << '\n';
}

word1: Log
word2: Bat
Thanks a lot for your explanation Chervil!!! I think I understand it better now.
Your first program was perfectly fine, it has only one error, at line 18:
1
2
	int len = 4; // len is not const, cannot be used as array size
	fmpz_t test[len]; // error here 

which should have said
1
2
	const int len = 4; // this fixes everything
	fmpz_t test[len]; 


Your first random_code actually passed the array by reference and it's a good thing to know how to do that since pointer and size is pretty much the worst possible interface a function that works on an array can have. (array by reference isn't perfect either, the best interfaces are iterator pair and array view - see ISO C++ Core Guidelines item I.13: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-i13-do-not-pass-an-array-as-a-single-pointer
Last edited on
Topic archived. No new replies allowed.