#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define MAX 100
void calc(float**, int, float*, float*);
int main( int argc, char* argv[] )
{
float *array[MAX];
float *MEAN;
float *SD;
int array_size, i;
array_size = argc;
for( i = 0; i < argc ; ++i )
{
*array = (float *) malloc( argc*(sizeof(float)));
*array[i] = atof(argv[i]);
}
calc(array, array_size, MEAN, SD);
return 0;
}
void calc(float* arr[] , int arr_size, float* mean, float* stdev)
{
int sum, i;
for ( i = 0; i < arr_size ; ++i )
{
sum += *arr[i];
}
*mean = sum / arr_size;
printf("%.2f", *mean);
for ( i = 0; i < arr_size ; ++i )
{
sum += pow((*arr[i]-*mean), 2);
}
*stdev = sqrt((sum/arr_size));
printf("%.2f", *stdev);
}
The code is supposed to determine the mean and standard deviation of a number of user-inputted floats. I keep getting a segmentation fault when trying to compile it. I tried freeing malloc but it produced more problems for the code, so I just left it as is - although it's probably a problem with memory distribution.
Thank you
There are several problems:
float *array[MAX]; is a pointer to an array of floats. You should
use either an array of floats or a pointer. Since you are using
malloc, you can use a pointer like this: float *array;
Do not call malloc for each float, but call it once for the entire array
If you define MEAN and SD as pointers, you will have to use
malloc on them. It is better to declare them as float only and use
their addresses (via &MEAN and &SD).
You sum variable should be a float, and you should initialize it
to 0. You should also set it to 0 before calculating stdev.
Remember that argv[0] contains the name of your program, so
you should ignore it.
Also remember to call free on anything you allocate with malloc
when you are done with it.
A modified version of your code:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
void calc(float*, int, float*, float*);
int main( int argc, char* argv[] ) {
float *array;
float MEAN;
float SD;
int array_size, i;
array_size = argc-1;
array = (float *) malloc( array_size*sizeof(float));
for( i = 0; i < array_size ; ++i ) {
array[i] = atof(argv[i+1]);
}
calc(array, array_size, &MEAN, &SD);
free (array);
return 0;
}
void calc(float* arr , int arr_size, float* mean, float* stdev) {
float sum=0;
int i;
for ( i = 0; i < arr_size ; ++i ) {
sum += arr[i];
}
*mean = sum / arr_size;
printf("%.2f ", *mean);
sum=0;
for ( i = 0; i < arr_size ; ++i ) {
sum += pow((arr[i]-*mean), 2);
}
*stdev = sqrt((sum/arr_size));
printf("%.2f", *stdev);
}
You are allocating and accessing array wrongly. Should be like this:
for( i = 0; i < argc ; ++i )
{
array = malloc( argc * sizeof(*array));
array[i] = atof(argv[i]);
}
Also inside calc() function change *arr[i] to arr[i] everywhere.
This is definitely wrong :
*array = (float *) malloc( argc*(sizeof(float)));
You are allocating an array of floats after declaring the array. This does not make sense. Then you are dereferencing the values wrongly. In addition, in your code your are trying to transform the name of the program (argv[0]) to an int type.
This may be what you wanted to do :
float * array = NULL;
array = malloc( (argc-1)*(sizeof(float)));
for (i=1; i<argc; ++i)
array[i]=atof(argv[i]);
This code reserves a memory location in the heap of size (argc-1)*float, and initialises it with the values specified as command line parameters. A check should be inserted when argc is 1.
You have several problems,
check that you have at least one argument
you declared array as an array of pointers to float, either use array[], or *array
your array need only be allocated once
allocate an array of number of samples*sizeof(float), once, before loop
store values read into array[ndx] locations (atof is fine)
argv starts at program name, store into array[n] the value converted from argv[n+1]
MEAN and SD need space, you declared pointers, change to value, and pass address (&)
Here is the revised main(),
int main( int argc, char* argv[] )
{
//float array[MAX];
float *array;
float MEAN;
float SD;
int array_size, ndx;
if(!(argc>0)) { printf("please give 1 or more arguments\n"); exit(1); }
array_size = argc-1; //don't count the program name
array = (float*) malloc(array_size*(sizeof(float)));
for( ndx = 1; ndx<argc ; ++ndx )
{
array[ndx-1] = atof(argv[ndx]);
printf("[%d] %f\n",ndx-1,array[ndx-1]);
}
calc(array, array_size, &MEAN, &SD);
free(array); array=NULL; //always clean up after yourself
return 0;
}
Your statistics calculations need work, but this at least compiles and runs,
you need to link against libmath (see below),
your sum was not initialized, before either loop,
pow and sqrt return double - read about C math functions and passing double,
your array_size needs to be set carefully
Here,
void calc(float arr[] , int arr_size, float* _mean, float* _stdev)
{
double sum, mean, stddev;
int i;
sum=0.0;
for ( i = 0; i < arr_size ; ++i )
{
sum += arr[i];
//printf("[%d] %f\n",i,arr[i]);
}
printf("sum %f\n",sum);
*_mean = mean = sum / arr_size;
printf("mean %f\n",mean);
printf("%.2f\n", *_mean);
sum=0.0;
for ( i = 0; i < arr_size ; ++i )
{
sum += pow((arr[i]-mean), 2);
//printf("[%d] %f\n",i,arr[i]);
}
printf("sum^2 %f\n",sum);
*_stdev = stddev = sqrt((sum/arr_size));
printf("stddev %f\n",stddev);
printf("%.2f\n", *_stdev);
}
Oh, you want to link to libmath,
cc stddev.c -lm -o stddev
And when running it,
$ ./stddev 1 2 3 4 5
[0] 1.000000
[1] 2.000000
[2] 3.000000
[3] 4.000000
[4] 5.000000
sum 15.000000
mean 3.000000
3.00
sum^2 10.000000
stddev 1.414214
1.41
Also, you need to free the memory you malloc'ed (array). This is good habit, though not needed for this tiny program.
Related
The task is to fill an array with numbers by user input and then use our stats() function to calculate average etc. of each row of this array. The header of stats() function looks as follows:
int stats(int (*ptr)[5], int width, int height, int row_id, int* max, int* min, float *avg)
where ptr is a pointer to the matrix,width and height are its size, row_id is the index of analysed row and max, min and avg are pointers to variables storing each statistics.
When calling a function with such line:
stats(*ptr, 5,5,2, *max = NULL, *min = NULL, *avg=NULL);
the following error appears:
error: invalid type argument of unary '*' (have 'int')
I tried different approaches but there is always a mistake, how can I fix that? Thank you for any clues.
edit:
Here's the whole code:
#include <stdio.h>
int stats(int (*ptr)[5], int width, int height, int row_id, int* max, int* min, float *avg)
{
int j, vmax,vmin;
int max = &vmax;
int min = &vmin;
int i = row_id;
int m = *ptr;
for(j = 0; j<5; j++){
if(m[i][j]>max)
{
max = m[i][j] ;
j++;
else
j++;
}
}
printf("%d", max);
return 0;
}
int main(void){
int n, i, j, vmin, vmax; // vmax - value of the maximum
int min = &vmin; // min - pointer to the minimum
int max = &vmax;
float vavg;
int avg = &vavg;
int m[5][5];
for(i = 0; i<5; i++)
{
for(j = 0; j<5; j++)
{
printf("ENTER A NUMBER: ");
scanf("%d", &n);
m[i][j] = n;
}
}
int ptr = &m;
stats(*ptr, 5,5,2, *max = NULL, *min = NULL, *avg=NULL);
return 0;
}
Your code full of bugs.
For example min and max are not declared as pointers
int min = &vmin; // min - pointer to the minimum
int max = &vmax;
Also it is unclear why the variable avg has the type int and is initialized by a pointer expression of the type float *.
float vavg;
int avg = &vavg;
Or the variable ptr of the type int is initialized by the address of the two-dimensional array.
int ptr = &m;
As for the function then if the function operates only on one row then there is no any sense to pass to the function the whole two-dimensional array.
Also the return type and the returned value of the function do not make a sense.
And the function shall not output any message. It is the caller of the function that will decide output a message or not.
And also the function contains bugs where you are redeclaring its parameters like for example
int max = &vmax;
that again does not make a sense.
Using your approach the function can be declared and defined the following way
#include <assert.h>
//...
void stats( const int *a, size_t n, int *max, int *min, float *avg )
{
assert( n != 0 );
*max = a[0];
*min = a[0];
float sum = a[0];
for( size_t i = 1; i < n; i++ )
{
sum += a[i];
if ( *max < a[i] )
{
*max = a[i];
}
else if ( a[i] < *min )
{
*min = a[i];
}
}
*avg = sum / n;
}
And called like
int min = 0;
int max = 0;
float avg = 0.0f;;
//...
stats( m[2], 5, &max, &min, &avg );
printf( "max = %d\n", max );
printf( "min = %d\n", min );
printf( "average = %f\n", avg );
When you are using pointers as function parameters be carefull. If you have something like this:
int func(int *max){
}
max ,here, is a pointer which needs to hold an address. So inside this function when you need use it, you need to dereference it by using *. For example:
int func(int *max){
*max = $someAddress
}
I don't really understand why method 1 works but not method 2. I don't really see why it works for characters and not an int.
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
/// WORK (METHODE 1)
char **string_array = malloc(sizeof(char **) * 10);
string_array[0] = "Hi there";
printf("%s\n", string_array[0]); /// -> Hi there
/// DOES NOT WORK (METHODE 2)
int **int_matrix = malloc(sizeof(int **) * 10);
int_matrix[0][0] = 1; // -> Segmentation fault
/// WORK (METHODE 3)
int **int_matrix2 = malloc(sizeof(int *));
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
int_matrix2[0][0] = 42;
printf("%d\n", int_matrix2[0][0]); // -> 42
}
In terms of the types, you want to allocate memory for the type "one level up" from the pointer you're assigning it to. For example, an int pointer (an int*), points to one or more ints. That means, when you allocate space for it, you should allocate based on the int type:
#define NUM_INTS 10
...
int* intPtr = malloc(NUM_INTS * sizeof(int));
// ^^ // we want ints, so allocate for sizeof(int)
In one of your cases, you have a double int pointer (an int**). This must point to one or more int pointers (int*), so that's the type you need to allocate space for:
#define NUM_INT_PTRS 5
...
int** myDblIntPtr = malloc(NUM_INT_PTRS * sizeof(int*));
// ^^ "one level up" from int** is int*
However, there's an even better way to do this. You can specify the size of your object it points to rather than a type:
int* intPtr = malloc(NUM_INTS * sizeof(*intPtr));
Here, intPtr is an int* type, and the object it points to is an int, and that's exactly what *intPtr gives us. This has the added benefit of less maintenance. Pretend some time down the line, int* intPtr changes to int** intPtr. For the first way of doing things, you'd have to change code in two places:
int** intPtr = malloc(NUM_INTS * sizeof(int*));
// ^^ here ^^ and here
However, with the 2nd way, you only need to change the declaration:
int** intPtr = malloc(NUM_INTS * sizeof(*intPtr));
// ^^ still changed here ^^ nothing to change here
With the change of declaration from int* to int**, *intPtr also changed "automatically", from int to int*. This means that the paradigm:
T* myPtr = malloc(NUM_ITEMS * sizeof(*myPtr));
is preferred, since *myPtr will always refer to the correct object we need to size for the correct amount of memory, no matter what type T is.
Others have already answered most of the question, but I thought I would add some illustrations...
When you want an array-like object, i.e., a sequence of consecutive elements of a given type T, you use a pointer to T, T *, but you want to point to objects of type T, and that is what you must allocate memory for.
If you want to allocate 10 T objects, you should use malloc(10 * sizeof(T)). If you have a pointer to assign the array to, you can get the size from that
T * ptr = malloc(10 * sizeof *ptr);
Here *ptr has type T and so sizeof *ptr is the same as sizeof(T), but this syntax is safer for reasons explained in other answers.
When you use
T * ptr = malloc(10 * sizeof(T *));
you do not get memory for 10 T objects, but for 10 T * objects. If sizeof(T*) >= sizeof(T) you are fine, except that you are wasting some memory, but if sizeof(T*) < sizeof(T) you have less memory than you need.
Whether you run into this problem or not depends on your objects and the system you are on. On my system, all pointers have the same size, 8 bytes, so it doesn't really matter if I allocate
char **string_array = malloc(sizeof(char **) * 10);
or
char **string_array = malloc(sizeof(char *) * 10);
or if I allocate
int **int_matrix = malloc(sizeof(int **) * 10);
or
int **int_matrix = malloc(sizeof(int *) * 10);
but it could be on other architectures.
For your third solution, you have a different problem. When you allocate
int **int_matrix2 = malloc(sizeof(int *));
you allocate space for a single int pointer, but you immediately treat that memory as if you had 10
for (int i = 0; i < 10; i++)
{
int_matrix2[i] = malloc(sizeof(int));
}
You can safely assign to the first element, int_matrix2[0] (but there is a problem with how you do it that I get to); the following 9 addresses you write to are not yours to modify.
The next issue is that once you have allocated the first dimension of your matrix, you have an array of pointers. Those pointers are not initialised, and presumably pointing at random places in memory.
That isn't a problem yet; it doesn't do any harm that these pointers are pointing into the void. You can just point them to somewhere else. This is what you do with your char ** array. You point the first pointer in the array to a string, and it is happy to point there instead.
Once you have pointed the arrays somewhere safe, you can access the memory there. But you cannot safely dereference the pointers when they are not initialised. That is what you try to do with your integer array. At int_matrix[0] you have an uninitialised pointer. The type-system doesn't warn you about that, it can't, so you can easily compile code that modifies int_matrix[0][0], but if int_matrix[0] is pointing into the void, int_matrix[0][0] is not an address you can safely read or write. What happens if you try is undefined, but undefined is generally was way of saying that something bad will happen.
You can get what you want in several ways. The closest to what it looks like you are trying is to implement matrices as arrays of pointers to arrays of values.
There, you just have to remember to allocate the arrays for each row in your matrix as well.
#include <stdio.h>
#include <stdlib.h>
int **new_matrix(int n, int m)
{
int **matrix = malloc(n * sizeof *matrix);
for (int i = 0; i < n; i++)
{
matrix[i] = malloc(m * sizeof *matrix[i]);
}
return matrix;
}
void init_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int **matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int **matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
Here, each row can lie somewhere random in memory, but you can also put the row in contiguous memory, so you allocate all the memory in a single malloc and compute indices to get at the two-dimensional matrix structure.
Row i will start at offset i*m into this flat array, and index matrix[i,j] is at index matrix[i * m + j].
#include <stdio.h>
#include <stdlib.h>
int *new_matrix(int n, int m)
{
int *matrix = malloc(n * m * sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[m * i + j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int *matrix)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[m * i + j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int *matrix = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
return 0;
}
With the exact same memory layout, you can also use multidimensional arrays. If you declare a matrix as int matrix[n][m] you will get what amounts to an array of length n where the objects in the arrays are integer arrays of length m, exactly as on the figure above.
If you just write that expression, you are putting the matrix on the stack (it has auto scope), but you can allocate such matrices as well if you use a pointer to int [m] arrays.
#include <stdio.h>
#include <stdlib.h>
void *new_matrix(int n, int m)
{
int(*matrix)[n][m] = malloc(sizeof *matrix);
return matrix;
}
void init_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 10 * i + j + 1;
}
}
}
void print_matrix(int n, int m, int matrix[static n][m])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
int main(void)
{
int n = 3, m = 5;
int(*matrix)[m] = new_matrix(n, m);
init_matrix(n, m, matrix);
print_matrix(n, m, matrix);
int(*matrix2)[m] = new_matrix(2 * n, 3 * m);
init_matrix(2 * n, 3 * m, matrix2);
print_matrix(2 * n, 3 * m, matrix2);
return 0;
}
The new_matrix() function returns a void * because the return type cannot depend on the runtime arguments n and m, so I cannot return the right type.
Don't let the function types fool you, here. The functions that take a matrix[n][m] argument do not check if the matrix has the right dimensions. You can get a little type checking with pointers to arrays, but pointer decay will generally limit the checking. The last solution is really only different syntax for the previous one, and the arguments n and m determines how the (flat) memory that matrix points to is interpreted.
The method 1 works only becuse you assign the char * element of the array string_array with the reference of the string literal `"Hi there". String literal is simply a char array.
Try: string_array[0][0] = 'a'; and it will fail as well as you will dereference not initialized pointer.
Same happens in method 2.
Method 3. You allocate the memory for one int value and store the reference to it in the [0] element of the array. As the pointer references the valid object you can derefence it (int_matrix2[0][0] = 42;)
I am trying to dynamically allocate an array, put some data in it, and then free it and set the array pointer to null so that it can not be accessed in the future. Also, unrelated, but I am storing the size of the array in the first element and then passing it back indexed one up, it is part of the assignment, so hopefully that doesn't confuse anyone.
If I am understanding the error correctly, I am trying to call free() on the array that my malloc'ed array was copied in to. This is not allowed because free() is not being called on the actual malloc'ed array but rather the one that's holding its values.
If this is the case, how would I fix my call of free() to only receive an array address and dereference it like free(*array);. Right now I have some mess of asteriscs and a cast and I have no idea why it works. If you know how to fix the free call into the above or just explain why what I have now works, I would greatly appreciate it. My goal is to be able to set the parameter for the custom free function to a void pointer instead of a specific data type pointer. Thanks!!
#include <stdlib.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(double ** array);
int main(void){
double * arr = createArray(10, sizeof(double));
int size = getSizeArray(arr);
/* using output for error checking
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
*/
void* p = &arr;
freeArray(p);
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return (void*) (array + 1);
}
void freeArray(double ** array){
free(*array);
*array = NULL;
}
EDIT: Look to #JonathanLeffler comment. The issue is with alignment. I switched around some of my code but I had to index back one and not cast in my functions but instead in main
#include <stdlib.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(double ** array);
int main(void){
double * arr = createArray(10, sizeof(double));
arr = (void*) (arr + 1);
int size = getSizeArray(arr);
/* using output for error checking*/
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
arr = (double*) (arr - 1);
freeArray(&arr);
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return array;
}
void freeArray(double ** array){
free(*array);
*array = NULL;
}
I provided a complete solution to this problem for another user. Must be a class assignment. My version is very similar to yours except I used macros instead of functions. Anyway, #Serge answer was so close. It -1 not +1.
Here what I plug into my code and it worked fine:
void freeArray(void** array)
{
free( ((int*)(*array)) - 1 );
*array = NULL;
}
Let me explain what going on. The C allocation routines are basically doing what you are doing. They save the array size one word above the actual array. Follow link for more information on how free() works. In our version, we are saving the array size one int (2 words/4 bytes) above the actual array. Your code was wrong because the address you reference is the 3rd element and not the first. You need to pass in the address where the array allocation originated which is ((int*)(*array)) - 1.
If you free(*array), you don't need to *array = NULL after that.
Also, you can't cast a (void *) onto an (int *) and assign it to a (double *).
Lastly, you can't freeArray(p); if p is a single pointer since freeArray(double ** array) has a parameter of double double-pointer.
Hopefully, this helps.
You can compare my modified code.
#include <stdlib.h>
#include <stdio.h>
int getSizeArray(void *array);
void * createArray(int n, int sizeOfDatatype);
void freeArray(void ** array);
int main(void){
double * arr = (double *)createArray(10, sizeof(double));
int size = getSizeArray(arr);
printf("size of arr %d\n", size);
// using output for error checking
for(int i = 0; i < 10; i++){
arr[i] = i;
}
for(int j = 0; j < 10; j++){
printf("%f\n", arr[j]);
}
void ** p = (void **)&arr;
freeArray(p);
printf("del arr, then arr = %u\n",(unsigned)arr);
}
int getSizeArray(void *array){
int s = ((int *) array)[-1];
return s;
}
void * createArray(int n, int sizeOfDatatype){
int * array = (int*)malloc((n * sizeOfDatatype) + sizeof(int));
array[0] = n;
return (void*) (array + 1);
}
void freeArray(void ** array){
free(((int*)*array)-1);
*array = NULL;
}
output:
size of arr 10
0.000000
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
9.000000
del arr, then arr = 0
I am trying to do complex vector addition and dot product using structures in C for a project. I have my code written, however, while it is compiling without a problem, once i run my program it stops working. I have other parts to the program but this is only the relevant part. I am also trying to do matrix addition and multiplication with complex numbers. I think I can modify the others if I can get these working. Any help at all would be appreciated. Thanks, I appreciate it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define PI 3.14159265359
typedef struct complex
{
double re;
double im;
}complex;
typedef struct vect_complex
{
double *re;
double *im;
}vect_complex;
typedef struct mat_complex
{
//int i=0,j=0;
double re[100][100];
double im[100][100];
}mat_complex;
void vector_add(vect_complex a[4], vect_complex b[4], vect_complex c[4])
{
int i;
for(i=0; i<3 ;i++);
{
c->re[i] = a->re[i] + b->re[i];
c->im[i] = a->im[i] + b->im[i];
}
printf("Vector addition = (%f + %f*j)i + (%f +%f*j)j + (%f + %f*j)k\n\n",c- >re[0],c->im[0],c->re[1],c->im[1],c->re[2],c->im[2]);
}
void addmx(mat_complex *a, mat_complex *b, mat_complex *c)
{
int i, j;
for ( i = 0 ; i < '\0' ; i++ )
{
for ( j = 0 ; j < '\0' ; j++ )
{
c->re[i][j] = a->re[i][j] + b->re[i][j];
c->im[i][j] = a->im[i][j] + b->im[i][j];
}
}
printf("***Matrix Addition***\n");
for ( i = 0 ; i < '\0' ; i++ )
{
for ( j = 0 ; j < '\0' ; j++ )
{
printf("(%f + %f*j) ", c->re[i][j],c->im[i][j]);
}
printf("\n");
}
}
int main()
{
vect_complex aaa;
vect_complex bbb;
*aaa.re = 5;
*aaa.im = 4;
*bbb.re = 3;
*bbb.im = 2;
vect_complex ccc;
vector_add(&aaa, &bbb, &ccc);
vector_dot_prod(&aaa, &bbb, &ccc);
return 0;
}
There are a number of issues to deal with here.
1. vect_complex
Perhaps you'd like your vect_complex to hold a fixed number of elements, in which case it should be defined:
typedef struct vect_complex
{
double re[3];
double im[3];
} vect_complex;
Alternatively, you can keep your current definition but you will need to allocate new arrays every time you use the structure:
int main(void)
{
vect_complex vc;
vc.re = (double *) malloc(3 * sizeof(double));
vc.im = (double *) malloc(3 * sizeof(double));
vc.re[0] = 1.0;
vc.im[0] = 2.0;
...
}
2. vector_add
This function should be taking references to vect_complex as inputs, not arrays of complex vectors. This implementation assumes the definition of vect_complex I gave above.
void vector_add(vect_complex * a, vect_complex * b, vect_complex * result)
{
int i;
for (i = 0; i < 3; i++)
{
result->re[i] = a->re[i] + b->re[i];
result->im[i] = a->im[i] + b->im[i];
}
}
3. addmx
I'm not sure what the '\0's are doing here. Change it to
for (i = 0; i < 100; i++)
for (j = 0; j < 100; j++)
{
...
}
At first, your program stops at the line *aaa.re = 5;
int main()
{
vect_complex aaa;
vect_complex bbb;
*aaa.re = 5; //your program stops here.
....
}
The reason is that you defined structure aaa which allocates memory for double pointer re and im , NOT for the double values.
As of now these pointers will point to uninitialized value. when you refer like *aaa.re ie) when you dereference it, you will get segmentation fault.
For example, aaa.re points to 0x17 in my box. when i dereference it, am getting segmentation fault, since it is referring the memory address which is out of program memory area.
To resolve this problem, you should allocate the memory for double and store the address
of it into the pointer re. Then store the double value.
Brain covered Other details perfectly.
Thanks,
nvseenu
#include <stdio.h>
#include <stdlib.h>
void setZero (double **, int);
int main (void) {
double *ptr = NULL;
int i, size = 3;
ptr = (double *)malloc(size * sizeof(double));
//*
setZero(&ptr, size);
/*/
// Sanity test
for ( i = 0 ; i < size ; ++i ) {
printf("index %d/%d\n", i, (size-1));
ptr[i] = 0; // NOT EXPLODING...
}
//*/
free(ptr);
return 0;
}
void setZero (double **_ref_array, int _size) {
int i;
for ( i = 0 ; i < _size; ++i ) {
printf("index %d/%d\n", i, (_size-1));
*_ref_array[i] = 0; // EXPLODING...
}
}
1) Why is this not working?
2) What is a "Bus error 10"
P.S. I know better than to initialize an array this way, but this just happens to be a simple and clean example of an underlying concept that I'm not understanding...
The dereference is happening after the index. I.e.
This says "Get the double pointer at index 'i', then set the value 0 to the memory at the address within that pointer."
*_ref_array[i] = 0;
This says "Get the address of the array of doubles from _ref_array, than index off that address by i-doubles.
(*_ref_array)[i] = 0;
On the face of the code given, you don't need to pass the address of the pointer to the function. You should be using:
void setZero(double *ptr, int size)
{
for (int i = 0; i < size; i++)
ptr[i] = 0.0;
}
and:
setZero(ptr, size);
The trouble you've got is as WhozCraig says:
*_array_ref[i]
is interpreted as:
*(_array_ref[i])
instead of:
(*_array_ref)[i]
as you need it to be. The former is trampling up the stack; the latter is initializing the allocated memory.
If you really must pass a pointer to a pointer to the function, then you can either wrap parentheses around the dereferences, or you can assign a local pointer and use that normally, right up to the point where you need to make use of the double pointer to change the value in the calling function.
void setZero(double **ptr, int size)
{
double *base = *ptr;
for (int i = 0; i < size; i++)
{
base[i] = 0.0;
// Or: (*ptr)[i] = 0.0;
}
...presumably some code here needs to assign to *ptr...
...if there is no such code, there is no need of the double pointer...
}