Estoy implementando un programa para dividir todos los valores en a matriz por 100 y luego almacenarlos en una matriz b usando malloc . El problema es que tengo una falla de segmentación al imprimir el valor de b en main .
este es mi codigo
#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; }Entonces, ¿qué causa este problema y cómo solucionarlo?
Gracias por adelantado.
Estás pasando el puntero b por valor a la función dividir
divide(a,5,b);Esa es la función que trata con una copia del puntero original. Cambiar la copia no influye en el puntero original.
Debe pasar el puntero por referencia a través de un puntero hacia él o rediseñar la función de tal manera que devuelva un puntero a la memoria asignada dinámicamente dentro de la función.
Por ejemplo, la función podría declararse y definirse de la siguiente manera
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; }Y en main puedes escribir
double *b = divide( a, sizeof( a ) / sizeof( *a ) );De lo contrario, la función puede verse como
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]); } } }y llamado como
divide( a, sizeof( a ) / sizeof( *a ), &b );Lo que recibe la función dividir es una copia del puntero b . Esto significa que la variable b en la función principal no cambia después de la llamada. Un ejemplo más simple para ilustrar esto es
void f(int n) { n = 1; }Después de que f ha sido llamado, n permanece sin cambios en el lado del llamador.
La corrección más simple de su código es hacer que divide reciba un puntero al puntero b . La firma de dividir sería entonces
void divide(int *a, int n, double **b);Sin embargo, es mejor asignar y liberar memoria en la misma función ya que es fácil olvidar que dividir asigna memoria. Cuando trabajo con matrices, siempre uso dos funciones macro convenientes NEW_ARRAY y LEN que simplifican el código. A continuación se muestra mi sugerencia. Si se cambia la longitud de a , el resto del código seguirá bien.
#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; }