I am implementing a program to divide all value in a
array by 100
then store them in b
array using malloc
. The problem is I got segmentation fault when printing value of b
in main
.
This is my code
#include <stdio.h>
#include <stdlib.h>
void divide(int *a, int n, double *b){
b=malloc(n*sizeof(double));
for(int i=0; i<n; i ){
b[i]=(double)a[i]/100.0;
}
//check: values still remain in b
for (size_t i = 0; i < 5; i )
{
printf("%.2f ", b[i]);
}
}
int main(){
int a[]={1,2,3,4,5};
double *b;
divide(a,5,b);
//check: lost value and cause segmentation fault
for (size_t i = 0; i < 5; i )
{
printf("%.2f ", b[i]);
}
free(b);
return 0;
}
So what cause this problem and how to fix it?
Thanks in advance.
CodePudding user response:
You are passing the pointer b by value to the function divide
divide(a,5,b);
That is the function deals with a copy of the original pointer. Changing the copy does not influence on the original pointer.
You need either to pass the pointer by reference through a pointer to it or redesign the function such a way that it will return a pointer to the dynamically allocated memory within the function.
For example the function could be declared and defined the following way
double * divide( const int *a, size_t n )
{
double *b = malloc( n * sizeof( double ) );
if ( b != NULL )
{
for ( size_t i = 0; i < n; i )
{
b[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i )
{
printf("%.2f ", b[i]);
}
}
return b;
}
And in main you can write
double *b = divide( a, sizeof( a ) / sizeof( *a ) );
Otherwise the function can look like
void divide( const int *a, size_t n, double **b )
{
*b = malloc( n * sizeof( double ) );
if ( *b != NULL )
{
for ( size_t i = 0; i < n; i )
{
( *b )[i] = a[i] / 100.0;
}
//check: values still remain in b
for ( size_t i = 0; i < n; i )
{
printf("%.2f ", ( *b )[i]);
}
}
}
And called like
divide( a, sizeof( a ) / sizeof( *a ), &b );
CodePudding user response:
What the function divide receives is a copy of the pointer b. This means that the variable b in function main is unchanged after the call. A simpler example to illustrate this is
void f(int n)
{
n = 1;
}
After f has been called, n is unchanged on the caller's side.
The simplest correction of your code is to make divide receive a pointer to the pointer b. The signature of divide would then be
void divide(int *a, int n, double **b);
However, it's better to allocate and free memory in the same function since it's easy to forget that divide allocates memory. When working with arrays I always use two convenient macro functions NEW_ARRAY and LEN which simplifies the code. Below is my suggestion. If the length of a is changed the rest of the code will follow nicely.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN(array) (sizeof (array) / sizeof (array)[0])
#define NEW_ARRAY(pointer, length) \
{ \
(pointer) = malloc(((size_t) length) * sizeof (pointer)[0]); \
if ((pointer) == NULL) { \
fprintf(stderr, "Allocating memory with malloc failed: %s\n", strerror(errno)); \
exit(EXIT_FAILURE); \
} \
}
void divide(int *a, int n, double *b)
{
for (int i = 0; i < n; i ) {
b[i] = a[i] / 100.0;
}
}
int main(void)
{
int a[] = {1, 2, 3, 4, 5};
double *b;
NEW_ARRAY(b, LEN(a));
divide(a, LEN(a), b);
for (size_t i = 0; i < LEN(a); i ) {
printf("%.2f ", b[i]);
}
printf("\n");
free(b);
return 0;
}