Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing pointer/array to main() from a function

I’m learning functions/pointers, and having a bit of an issue. What I need to write is a C program with main() and two other functions.

Requirements:

  1. read_funct() must allocate enough memory using malloc() to store the data.

  2. Function prototype for read_funct must be:

    int read_funct(int *data_num, double **data_vals, char *filename)
    

How it’s meant to work:

  1. main() calls the first function: read_funct()

  2. read_num() reads binary data from a file. Two values have to be extracted: the no. of values (first 4 bytes), then the values themselves (8 bytes each, so contained in the next 8*no. of values). These correspond to data_num and data_vals. They have to be printed, the program then returns to main().

  3. main() performs operations to edit the data from the first file.

  4. main() calls the second function: write_funct(), which writes the edited data into a new file.

Where I am:

The first function reads data_num correctly, and reads/prints data_vals. This is all working properly. However, I’m trying to print these in main() to verify that I’m performing operations on the correct data, but I can’t get it working.

Note: I’m not trying to get it working with write_funct() at the moment, just taking it step-by-step.

Here’s my current code for main():

int read_funct(int *data_num, double **data_vals, char *filename);
int main()
{
  int data_num;
  double **data_vals;

  //Reads file using read_funct()
  read_funct(&data_num, data_vals, filename);

  //Check: print data_num
  printf("\nCheck No. of Values: %d\n", data_num);

  //Check: print data_vals
  for(int i = 0; i<data_num; i++)
  {
        printf("%0.3lf\t", data_vals[i]);
  }
  return(0);
}

Here’s read_funct()

int read_funct (int *data_num, double **data_vals, char *filename)
{
    FILE * fp = fopen(filename, "rb");                          //Opening file      
   //There's code here to check valid file open

   //There's code here to determine size and check valid length

  //Proceed with reading data_num if file is large enough
  char buffer_n[4];
  fread(buffer_n, 4, 1, fp);
  int res = buffer_n[0]|(buffer_n[1] << 8)|(buffer_n[2] << 16)|(buffer_n[3] << 24);     //Convert endian

  data_num = &res;          //Passes results back to data_num
  printf("Number of Data Values: %d \n", *data_num);    //Printing results

  //Proceeds with calculating data_vals
  data_vals = malloc(8*res);                //Allocating memory
  fread(data_vals, 8, res, fp); 

    //Prints data_vals
    for(int i=0; i<res; i++)
    {
        printf("%0.3f\t", data_vals[i]);
    }
    printf("\nEnd of File Read.\n\n");
    fclose(fp); 
    free(data_vals);                //Free allocated memory
    return(0);
}

Desired output:

Basically, I want it to print out the values from inside read_file() and then print a check in main(), so the output will be something like:

No. of values: 3            //From printf in read_file()
2 4 6

Check No. of values: 3      //From printf in main()
2 4 6

Where I think I'm going wrong:

  1. Fairly sure that the main issue is that I've messed up my pointers and how I've initialised things in main(). I've been trying to fix this by myself, but I think I need some more experienced help to figure this out.

  2. I know that every malloc() call must have a subsequent free(), but I'm worried that by doing so the way that I have, maybe I've made it so that I can't retrieve it in main(). Does it instead need to have an intermediate buffer to which memory is allocated instead?

Help to get this code working would be very greatly appreciated. Thank you!

like image 424
ReyL Avatar asked Apr 09 '17 01:04

ReyL


People also ask

Can We pass array to function as pointer?

Since array and pointers are closely related to each other. Hence you can also pass an array to function as pointer. Important Note: Arrays in C are passed as reference not by value. Which means any changes to array within the function will also persist outside the function. How to return single dimensional array from function?

How do you pass an array to a function in C?

Pass the returned array as parameter Arrays in C are passed by reference, hence any changes made to array passed as argument persists after the function. So you can accept the output array you need to return, as a parameter to the function. The above program on execution prints. How to pass multi-dimensional array to function?

How do you pass an array as a parameter in Python?

Syntax for Passing Arrays as Function Parameters. The syntax for passing an array to a function is: returnType functionName(dataType arrayName[arraySize]) { // code } Let's see an example, int total(int marks[5]) { // code } Here, we have passed an int type array named marks to the function total(). The size of the array is 5.

How to pass a pointer to a function in C?

Passing pointers to functions in C. C programming allows passing a pointer to a function. To do so, simply declare the function parameter as a pointer type.


1 Answers

Apart from freeing the data too soon, you have another problem here:

double **data_vals;
read_funct(&data_num, data_vals, filename);

If you want data_vals to be filled (written to, modified) by a function, you must pass its address, exactly as you do with data_num.

Here is another, slightly different, explanation. You see, you declare data_vals but you don't assign a value to it - it contains garbage. So it is a non-sense to pass data_vals to any function, or use it in any expression. It has a sense instead, to assign something to it, either via direct assignment or passing its address to a function, for the function to fill the variable.

Then, your usage of data_vals depicts a vector, or an array. So you really need to declare an array with [], or may be a pointer (pointers and arrays are quite related/interchangeable in C). The logic of your main() function requires a pointer, not a pointer to pointer. Hence, this is appropriate:

double *data_vals;

The function which writes to your pointer variable, instead, needs the address of the variable to write to; in other words: a pointer to a pointer. This is why your function has this (correct) signature:

read_funct(..., double **data_vals, ...)

To understand easily, let see the other (simpler) thing you wrote correctly:

int data_num;
read_funct(&data_num, ...);  // declaration: read_funct(int *data_num, ...)

You declare data_num as integer in main(); you declare read_funct() with a formal parameter of pointer to integer, then you call read_funct() passing the address of your variable data_num. Perfect. Now, do the same with the other variable, data_vals. You declare it as pointer to double, pass its address to read_funct() using the notation &data_vals, and your function read_funct() declares that parameter as a pointer to pointer to double (and writes to it using *data_vals = .... You can see the parallelism between the two variables, right?

May be I've been too pedantic, but your question was really clear and well formed, so I tried to do the same.

like image 177
linuxfan says Reinstate Monica Avatar answered Oct 19 '22 21:10

linuxfan says Reinstate Monica