I have the following functions:
int sum(int *a, int size) {
int sum;
int i;
for(i = 0; i < size; i++) {
sum += a[i];
}
return sum; /* Change the return value */
}
and
double average(int *a, int size) {
int summation = sum(*a, size);
double result = (double) summation/size;
return result; /* Change the return value */
}
and when I compile, I get the error: passing argument makes pointer from integer without a cast
What should I change?
In your average function, don't pass *a to sum, but just a since it's already a pointer.
Since a is an array, just passing a will give the base address of the array, so just pass a in the argument.
Related
I have a segment fault int this exercice.
Instruction:
• Write an ft_ultimate_range function which allocates and assigns an int array. This int table will contain all values between min and max.
• Min included - max excluded.
• If the min value is greater than or equal to the max value, range will point to NULL.
• The range size will be returned (or 0 in the event of a problem).
#include <stdlib.h>
#include <stdio.h>
int ft_ultimate_range(int **range, int min ,int max)
{
int len;
int i;
i = 0;
len = max - min;
if (min >= max)
{
*range = NULL;
return(0);
}
**range = (int)malloc(sizeof(int) * len);
while (min < max)
{
range[0][i] = min;
i++;
min++;
}
return(len);
}
int main()
{
int min;
int max;
int **range = NULL;
min = 0;
max = 10;
printf("%d\n", ft_ultimate_range(range, min, max));
return(0);
}
**range = (int)malloc(sizeof(int) * len);
This line raises the warning when i compile your code:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
Never ignore the warning from the compiler.
malloc function returns a pointer, why do you cast it to int value ?
You want 2D array, but i seems that is matrix 1 x len, it's 1D array (vector).
OK, forget the 2D or 1D array (vector). If you want to use double pointer in your code, you have allocate for it first.
// this line should be in main function
range = malloc(sizeof(int *));
if(!range) {
return -1;
}
// this line before while loop
range[0] = malloc(sizeof(int)*len);
if(!range[0]) {
return -1;
}
If you want a matrix "M*N", you can allocate the pointer as below:
// allocate double pointer
range = malloc(sizeof(int *)*M);
if(!range) {
return -1;
}
// then using a loop to allocate the pointers:
for(int i = 0; i<N; i++) {
range[i] = malloc(sizeof(int)*N);
if(!range[i]) {
return -1;
}
}
Do not forget to free the pointer when you do not need to use (free(range[i] then free(range)).
As you have guessed your allocation is wrong
by writing
**range = (int)malloc(sizeof(int) * len);
you meant to assign to the dereference of the dereference of range (NULL)
range = NULL
*range = whatever value is at offset 0
**range = whatever value is at the address from the value read at address 0
please read this for writing the allocator
it would boil down to:
array = malloc( sizeof(int[rows][cols]) );
but in your case you want to return the array as a pass by ref var
int main() {
int **array;
ft_ultimate_range(&array)
}
int ft_ultimate_range(int ***array) {
*array = malloc( sizeof(int[rows][cols]) );
}
BUT
your code is kind of not using the full 2d array and the function is not returning it:
while (min < max)
{
range[0][i] = min;
i++;
min++;
}
you are only using one row here, and not even using the data in range after that, one would think the code to be irrelevant, as you are only returning len.
I'm trying to protect the -a- array of the my_sum_array function from the changes. In the function block I do not make any changes to -a-, but I have a warning (warning: assignment to 'int *' from 'const int *' discards the qualifiers [-Wincompatible-pointer-types-discards-qualifiers]). I know I could remove const to make the program work, but I would like to understand if something is missing from me.
#include <stdio.h>
#define MAX 5
int my_sum_array(const int a[], int n);
int main(void) {
int values[5] = {4, 7, 1, 7, 8};
printf("The sum in my_sum_array is :%d\n", my_sum_array(values, MAX));
return 0;
}
int my_sum_array(const int a[], int n) {
int *p, sum = 0;
for (p = a; p < a + n; p++)
sum += *p;
return sum;
}
The warning is caused by the assignment p = a in the for loop. The variable is defined as int *p, a pointer to non-const int. The warning is correct, "assignment to int * from const int * discards the qualifiers". It's as though you've casted away the constness of the a pointer parameter.
I'd change your function to:
int my_sum_array(const int a[], int n) {
int sum = 0;
for (const int *p = a; p < a + n; p++)
sum += *p;
return sum;
}
This defines p as a pointer-to-const, just like a, and also limits its lifetime to the for loop.
Make your p pointer as:
int const * p;
i.e.
here, p is a pointer to a const integer
Change type of p to:
const int *p;
So now you end up with:
const int * p;
int sum = 0;
int* sum(int *mypt,int len){
int i;
int mysum = 0;
for(i=0;i<len;i++)
mysum += mysum;
return &mysum; // I cannot do this since the function frame goes away after the call.
}
int main()
{
int *pt = (int*) malloc(3*sizeof(int));
pt[0] = 0;
pt[1] = 1;
pt[2] = 2;
int *s = sum(pt,3);
printf("%d\n",*s);
return 0;
}
I would like to return a pointer to the mysum. I cannot do int static sum = 0 because it is fixed. I cannot use int const sum = 0 because it gives an error ""readonly"". Is there a solution to this ?
why do you need to return a pointer from sum() you can just return the answer by value. If you must return a pointer, than you will need to malloc() the memory inside of sum() and the caller of sum will have to free() the answer, but that is not very efficient.
int sum(int mypt, len)
{
int i;
int mysum = 0;
for(i=0;i<len;i++)
mysum += mysum;
return mysum; // return the answer by value.
}
And change main() as below:
int main()
{
int *pt = (int*) malloc(3*sizeof(int));
pt[0] = 0;
pt[1] = 1;
pt[2] = 2;
int s = sum(pt,3);
printf("%d\n",s);
return 0;
}
Yes, use malloc to place the integer in heap memory and obtain a pointer. You can then return this pointer from the function:
int* sum(int *mypt, int len) {
int i;
int* mysum = malloc(sizeof(int));
//make sure you dereference (*) when you wish to work with the value.
*mysum = 0;
for(i=0; i<len; i++) *mysum += *mysum;
return mysum;
}
Aside, it looks like a lot of your code is broken. This only solves how to return the pointer!
#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...
}
I have the following warnings during the compilation:
solver.c:24: warning: passing argument 2 of ‘mtrx_multiple’ from incompatible pointer type
mat.h:5: note: expected ‘double *’ but argument is of type ‘double **’
solver.c:30: warning: assignment makes pointer from integer without a cast
solver.c:39: warning: assignment makes pointer from integer without a cast
/tmp/ccmU9zRf.o: In function `vec_norm':
math.c:(.text+0x331): undefined reference to `sqrt'
collect2: ld returned 1 exit status
the lines are:
solver.c
double *cg_solve( sparse_mat_t A, double *b, double *x ) {
double *a;
double **r;
double *be;
double **p;
double **x0;
x0[0] = vec_copy(x, size);
...
line 24: r[0] = vec_subtraction( b, mtrx_multiple(A, x0), size );
line 30: x0[k+1] = vec_addition( x0[k], vec_numb_multiple(a[k], p[k], size), size );
line 39: p[k+1] = vec_addition( r[k+1], vec_numb_multiple(be[k], p[k], size), size );
}
math.h
line 5: double *mtrx_multiple (sparse_mat_t A, double *c);
The function that are used there: (math.c)
double *vec_subtraction (double *a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a[i]-b[i];
return result;
}
double *vec_addition (double *a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a[i]+b[i];
return result;
}
double *vec_numb_multiple (double a, double *b, int n) {
double *result = malloc(sizeof(double)*n);
int i;
for(i=0; i<n; i++)
result[i] = a*b[i];
return result;
}
double *mtrx_multiple (sparse_mat_t A, double *c) {
double *result;
int i, j;
result = malloc((A.size) * sizeof *result);
printf("c.n: %d \n", A.size);
for (i = 0; i < A.size; i++) {
int v = 0;
for (j = A.ia[i]; j < A.ia[i + 1]; j++) {
v += A.a[j] * c[A.ja[j]];
}
result[i] = v;
}
return result;
}
double vec_norm (double *a, int n){
double result;
int i;
for(i=0; i<n; i++)
result = result + ( a[i] * a[i] );
result = sqrt(result);
return result;
}
double *vec_copy (double *a, int n) {
double *result;
int i;
for(i=0; i<n; i++)
result[i] = a[i];
return result;
}
I will be grateful for any help.
EDIT
I found the solution to the x0 problem, thanks Ben. Now what left is:
solver.c:30: warning: assignment makes pointer from integer without a cast
solver.c:39: warning: assignment makes pointer from integer without a cast
/tmp/ccL4uSoH.o: In function 'vec_norm':
math.c:(.text+0x331): undefined reference to 'sqrt'
collect2: ld returned 1 exit status
Based on what you've posted, I'm going to guess that you don't have a declaration for vec_numb_multiple in scope before you call it, and the compiler is implicitly typing it to return int; that would lead to the warnings on lines 30 and 39.
The undefined reference to sqrt() means you aren't linking in the standard math library; I'm assuming you're using gcc, so you would need to add -lm to the command line.
It's a really bad idea to use a standard library file name for your own code (math.h, math.c).
replace (line 24)
r[0] = vec_subtraction( b, mtrx_multiple(A, x0), size );
with
r[0] = vec_subtraction( b, mtrx_multiple(A, x0[0]), size );
You said you whant to multiply a matrix (A I guess) with a vector, so the second argument must be a vector. x0 is a pointer to pointers which can be see as a 2D array of doubles, it means a single cell of x0 is an array of doubles (ie. what you could call a vector). This is why you want to pass x0[0], not just x0 which is : many arrays.
see John's aswer for the rest.