0

I created a header file called primes.h. What I want is to call a function generate_primes() defined in this header file to fill an array with a determined number of prime numbers.

So to test if everything works fine, I first printed the elements of the array from 'inside' the header file' which works just fine. Then I tried printing them from outside the header file, in the program including the header file but it's not working, and the program just stops after printing a few elements. Why is this unproper behaviour? And how can I do this the right way. Thanks for helping.

The header file:

int generate_primes(const unsigned long long n, unsigned long long*prime) 
{

    try
        {
            prime = new unsigned long long[n]; 
        } 
    catch(const std::bad_alloc&e) {
        std::cerr << e.what(); 
        exit(EXIT_FAILURE);  
    }

    prime[0] = 2, prime[1] = 3, prime[2] = 5; 

    unsigned long long p;
    unsigned long long index = 3;

    for (p = 7; index < n; p += 2)
        {
            short isPrime = 1; 
            unsigned long long test_limit = (unsigned long long) sqrt(p); 

            for (int i = 1; prime[i] <= test_limit && i < index; i++)
                {
                    if (!(p%prime[i]))
                        {
                            isPrime = 0; 
                            break;  
                        }   
                } 
            if (isPrime) prime[index++] = p; 
        }

    //everything works fine when I print from inside the header file 
    /*for (int i = 0; i < n; i++)
      {
      if (i && i % 7 == 0) std::cout << '\n'; 
      std::cout << prime[i] << "\t\t"; 
      }
    */
    return 1; 
}

My program:

#include <iostream>
#include <cmath>
#include <vector>
#include <new>
#include <cstdlib>
#include "primes.h"

int main(){
    unsigned long long n = 100;//example  
    unsigned long long *prime;   
    generate_primes(n, prime); 

    //but printing from here causes problems 
    //isn't the array now filled after calling the above function ? 
    for (unsigned long long i = 0; i < n; i++) 
        {
            if (i && i % 5 == 0) std::cout<< '\n'; 
            std::cout << prime[i] << "\t"; 
        } 

    return 0; 
}
8
  • 1
    Don't put function definitions in header files. Commented Jul 12, 2017 at 19:43
  • 1
    Indentation is not something you should neglect this badly. Commented Jul 12, 2017 at 19:45
  • 1
    So what is the actual output of your program? Commented Jul 12, 2017 at 19:47
  • Sorry. I'll make sure I'll do that the next time. Commented Jul 12, 2017 at 19:47
  • 1
    Your problem is that the pointer parameter is only changed within the function but not reflected outside. You can change the parameter signature like this: unsigned long long*&prime to get your code working. Commented Jul 12, 2017 at 19:47

3 Answers 3

2

The problem is that the parameter prime is being passed by value, not by reference. So when generate_prime assigns:

prime = new unsigned long long[n];

this only assigns to the local variable prime, not the caller's variable. You need to pass the parameter by reference so that the assignment will be visible to main().

int generate_primes(const unsigned long long n, unsigned long long*&prime) 
Sign up to request clarification or add additional context in comments.

7 Comments

It would generally be better to just allocate the whole array at the caller's side and manage it's lifetime from there. Now it is unclear who and how should take care of the array. Then you wouldn't even have such issues.
@K.Kirsz And it would be even better to use std::vector so this whole thing becomes moot.
@K.Kirsz The best way would be to use a std::vector reference parameter.
Thank's. I just meant to have this part of code seperated and be able to use It whenever I need It.
@lamriniyounes There's a lot of valid criticisms here you should pay attention to. Code separation is just one problem.
|
0

That's not a header file, it's a bunch of code. If you want to separate that code it should be in another .cpp file.

An associated .h would look like this:

#include <cmath>
#include <vector>
#include <new>

int generate_primes(const unsigned long long n, unsigned long long*prime);

Then you'd have generate_primes.cpp or something like it:

 #include "generate_primes.h"

 int generate_primes(const unsigned long long n, unsigned long long*prime) {
   // (function body)
 }

To build your application you'd need to compile both .cpp files and link them together with the required libraries.

2 Comments

You're right, It's not. What I meant to do is to have this part of code seperated since I use It alot. Then be able to call It whenever I need It.
That's exactly why you break out your code into multiple .cpp files, and each .cpp with functions in it has an associated .h file that defines what those are. This complicates compilation, but you'll have to commit to a Makefile, or something like it eventually anyway. With a good compiler setup then only .cpp files which need to be recompiled will be compiled during a routine build, and this can speed up development considerably. the way you have it in the .h file leads to cascading rebuilds even if the function signature is untouched.
0

The value of the uninitialized pointer prime is an argument to the call of generate_primes. There it is not evaluated but the parameter assigned a new (local) value. Therefore inside the method the Array is accesible. But the new value is never returned, so in main the value of prime remains unchanged.

Additionally you should change n from unsingned long long to a smaller type for teh sake of the compiler.

Two possible solutions: a) modify generate_prime so that it return the address of the Array

unsigned long long *prime generate_primes(const unsigned long n) 

b) gíve the address of the pointer as an Argument to the method

int generate_primes(const unsigned long n, unsigned long long **prime) 
{

    try
    {
        *prime = new unsigned long long[n]; 
    } catch (const std::bad_alloc &e) {
    // your code

and

int main(){
    unsigned long n = 100;//example  
    unsigned long long *prime;   
    generate_primes(n, &prime);

    // your Code

    delete[] prime; // free memeory
    return 0; 
}

1 Comment

Thank's. I tried : int generate_primes(const unsigned long long n, unsigned long long*&prime) wich is the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.