Unable to properly use struct pointers in C - c

I am a beginner with C and currently struggling with using structs in functions. Even tho I give my functions the pointer to my struct and use that to change their values it seems like my functions are unable to change the value of the pointer themselves
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
typedef struct Vector
{
int n;
double *entry;
}Vector;
//defining the struct vector with n for its length and entry as a pointer which will become an array for its values
Vector *newVector(int n)
{
int i = 0;
Vector *X = NULL;
assert(n > 0);
X = malloc(sizeof(Vector));
assert(X != NULL);
X->n = n;
X->entry = malloc(n+1*sizeof(double));
assert(X->entry != NULL);
X->entry[0] = 0;
for (i=1; i<n+1; ++i) {
scanf("%lf",&X->entry[i]);
}
return X;
}
//making a new vector struct from the size given and returning its pointer (the array is made so it goes from 1-n instead of 0-(n-1)
void delVector(Vector *X)
{
assert(X != NULL);
assert(X->entry != NULL);
free(X->entry);
free(X);
X = NULL;
}
int getVectorLength (Vector *X)
{
assert(X != NULL);
return X->n;
}
void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
} //deleting the vector and then replacing it with the new sized vector
double getVectorEntry (Vector *X, int h)
{
return X->entry[h];
}
void setVectorEntry (Vector *X, int h)
{
printf("Value %d.\n",h);
scanf("%lf",&X->entry[h]);
}
main()
{
Vector *h = NULL;
h = newVector(3);
printf("%f\n",h->entry[1]);
printf("%f\n",getVectorEntry(h,1));
setVectorEntry(h,1);
printf("%f\n",getVectorEntry(h,1));
printf("%d\n",getVectorLength(h));
setVectorLength(h,6);
printf("%f\n",getVectorEntry(h,6));
setVectorEntry(h,6);
printf("so far.\n");
printf("%f\n",getVectorEntry(h,6));
}
Running the code would make it crash once it reaches delVector. If I were to comment the delVector out it would crash at X = newVector(k); for a reason I also cannot find out (it starts the function newVector, but crashes before I can input). So what is causing the errors?
Thanks a lot in advance!

Let's just focus on the setVectorLength function
void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
}
Here, Vector *X is a local variable that only exists in this function. It points to some location in memory, but using it you can't modify the original pointer. So there are two ways around it.
1. You don't delete and recreate the vector. Instead do something like this
void setVectorLength(Vector *X, int k)
{
X->entry = realloc(X->entry, k*sizeof(double)); // frees X->entry and allocates it to a new heap array
X->k = k;
}
2. Use a pointer pointer. Do note, that this will be slower and is unnecessary. Go for the 1 solution.
void setVectorLength(Vector **X, int k)
{
assert(*X != NULL);
assert(k>0);
delVector(*X);
printf("so far.\n");
*X = newVector(k);
}
The variable Vector **X points to the original variable, so you can modify it.

Problem seem to be in function
Vector *newVector(int n)
{
int i = 0;
Vector *X = NULL;
assert(n > 0);
X = malloc(sizeof(Vector));
assert(X != NULL);
X->n = n;
X->entry = malloc(n+1*sizeof(double));
assert(X->entry != NULL);
X->entry[0] = 0;
for (i=1; i<n+1; ++i) {
scanf("%lf",&X->entry[i]);
}
return X;
}
In above statement, you are allocating X->entry with n + sizeof(double) but as per your requirement you should allocated (n + 1) * sizeof(double)
You should allocate memory for X->entry as
X->entry = malloc((n + 1) * sizeof(double));

Your allocation is wrong, you have to group the n and the 1 like you do it on paper so. Not that the expression you have n + 1 * sizeof(double) means the same as n + sizeof(double).
X->entry = malloc((n + 1) * sizeof(*X->entry));
would be the right way!
As it was, your code invokes undefined behavior and once possible consequence is for the program to crash. Most likely because trying to access memory out of it's memory space so a segmentation fault occurs.

void setVectorLength(Vector *X, int k)
{
assert(X != NULL);
assert(k>0);
delVector(X);
printf("so far.\n");
X = newVector(k);
}
In this function, X is a copy of the pointer variable the caller passes in. It contains a copy of the address. Modifying a function parameter doesn't change the caller's value. Just as doing k = 0 would have no effect on the caller, reassigning X is a local change that is invisible to the caller.
If you want the caller to see the result of newVector(k), you have a couple options. You could change setVectorLength() to work like newVector() and return the new pointer.
Vector *setVectorLength(Vector *X, int k) {
...
printf("so far.\n");
return newVector(k);
}
int main() {
...
h = setVectorLength(h, 6);
}
Or you could add another layer of indirection—make X a pointer to a pointer. That would require the caller to pass the address of the variable they want changed. Instead of passing h you'd pass &h.
void setVectorLength(Vector *X, int k) {
...
printf("so far.\n");
*X = newVector(k);
}
int main() {
...
setVectorLength(&h, 6);
}
By the way, the way you've written setVectorLength(), it will destroy any existing data in the vector. You may want to copy the data from the old vector to the new one. (Or, as #pi_pi3 suggests, modify the vector in place instead of destroying it and creating a new one.)

Related

How to return int array in C using this Collatz Conjecture function?

I have a function for the Collatz Conjecture that returns an int Array but I keep getting a segmentation fault error and am not sure why.
int n=1;
int* col fuction(int x){
int *totalList;
totalList[0]=x;
while (x != 1){
if (x%2==0){
x=x/2;
}else{
x= 3* x + 1;
}
totalList[n]= x;
n++;
}
totalList[n+1]=1;
return totalList;
}
It is suppose to return the integers in a row with commas in between each number. I call it as shown below:
int *colAns;
colAns= col(num);
for (int k =0; k< n; k++){
printf("%d", colAns[k]);
if(colAns[k] != 1){
printf(",");
}
}
printf("\n");
Your issue lies within the first few lines of col_function().
int* col_fuction(int x){
int *totalList;
totalList[0]=x;
// ...
}
When the int* called totalList gets created on the stack, it takes whatever value was previously there. There's a slim chance that the pointer value will be anything even owned by the process, let alone something valid/usable.
What you need is a dynamically-allocated value that can grow as values are added to it. For this, we use malloc to allocate a pre-determined amount of memory. Because the collatz function is recursive and the number of elements cannot be determined by merely looking at it, we cannot presume to know exactly how much memory it will take, so it should grow as numbers are added to it. For this, we use realloc. What's nice about realloc is that, if the first parameter is NULL, it is guaranteed by the standard to work like malloc.
The only other thing you really need is a couple of size_t values inside of a struct in order to keep track of the current index as well as the allocated space. Something like this should be sufficient:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define CHUNK_SIZE 100
typedef struct dynarray
{
int *values;
size_t allocated, used;
} dynarray;
int dynarray_init(dynarray *d)
{
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_deinit(dynarray *d)
{
free(d->values);
memset(d, 0, sizeof(dynarray));
return 0;
}
int dynarray_append(dynarray *d, int val)
{
int *tmp = NULL;
size_t i;
if(d->used + 1 >= d->allocated)
{
if((tmp = (int*)realloc(d->values, (d->allocated + CHUNK_SIZE)*sizeof(int))) == NULL)
{
perror("realloc() failure");
return 1;
}
else
{
d->values = tmp;
d->allocated += CHUNK_SIZE;
}
}
d->values[d->used++] = val;
}
Use dynarray_append() to add values to the list after it's been initialized.

Create a d-dimensional pointer [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
We use to indicate a pointer with the symbol *. Iterating the procedure, we obtain a "double" pointer **, a "triple" pointer *** and, more generally, a "d-dimensional" pointer (for each d positive natural number).
Problem: given such a d as an input, define S to be a d-dimensional pointer.
Because I started studying dynamic structures only some days ago, I am unfortunately a bit in trouble with this problem.
Does anyone have a suggestion/hint?
Thank you in advance, and my apologies for my probably too basic question.
Ps: I used the word "pointer" without specify its type only for sake of brevity.
This problem has a solution in C as long as two conditions are met:
The value of d is known at compile time, and
d has a pre-defined limit, e.g. 10
You can solve this problem by defining a series of macros and "pasting" the value of d as a token:
#define D_PTR(d,T) D_PTR##d(T)
#define D_PTR0(T) T
#define D_PTR1(T) T*
#define D_PTR2(T) T**
#define D_PTR3(T) T***
...
#define D_PTR10(T) T**********
Now you can declare d-dimension pointers like this:
D_PTR(5,int) ptr5 = NULL;
Demo.
There are three distinct ways to solve this:
Your d is a compile-time constant. For this case, dasblinkenlight has already given the solution.
The hacky-C solution: Just use a cast to get back to the pointer type:
double* dereferenceDLevels(double* pointer, int d) {
for(; d--; ) pointer = *(double**)pointer;
return pointer;
}
I do not recommend this approach, though. It's just too dirty.
You implement your d-level pointers as user defined types:
typedef struct nLevelPointer {
int n;
union {
nLevelPointer* pointer;
double value;
};
} nLevelPointer;
double nLevelPointer_dereference(nLevelPointer* me) {
for(int i = me->n; i--; ) me = me->pointer;
return me->value;
}
I consider this approach the cleanest and most flexible one. However, it has the trade-off of requiring a significant amount of boilerplate code to make it fly.
Basically the number of * represents the number of indirections to reach the variable. So you have to create d indirections. I assume this has no practical application - that's an answer to a recreative problem.
An indirection in C is an address, a pointer. Creating d indirections means the creation of d addresses to reach a variable data (the space allocated to the variable of type T).
p(d) -> p(d-1) -> ... -> p(1) -> variable
To create dynamically such a structure, you could do it via malloc (replace T with any known type), and - since you may not specify the number of * dynamically to a pointer - requires some C hacking.
So, again, this is not something recommended and is a particularly bad design, especially for inexperienced C developers. Purpose is to show it could be done dynamically, whatever the value of d.
Say T is a double
int d = ...; // from input (d >= 1)
double variable;
double **S = malloc(sizeof(double *) * d); // array of pointers to pointer
S[d-1] = &variable; // last address points to target
int i;
for(i=d-2 ; i>=0 ; i--) S[i] = (double *)&S[i+1]; // previous address
// points to next location
There is no way to represent an arbitrary number of indirections in C, so S is only a ** to satisfy the compiler requirements, and is cast when necessary.
Let's try with d set to 4 and applying the algorithm above (say T is a double), having
double variable is at address 0100 (decimal), value 3.14
S address given by malloc at 1000
a pointer size being 4
a double size being 8
variable
v
[8 bytes double value 3.14]
^
0100
S
v
[1004][1008][1012][0100]
^ ^
1000 1012
Now the structure is in place, how to use/test it? You could create a function that returns the type T (double here), take the S value and d, operate the d indirections and return the variable
double getvariable(double **S, int d) {
while (--d > 0) S = (double **)*S; // d-1 iterations
return *(double *)*S;
}
trying it
printf("%lf\n", getvariable(S, d)); // 3.14
to test the above structure without a function, for d == 4, you could create
double ****p = (double ****)*S;
printf("%lf\n", ****p); // 3.14
Problem: given such a d as an input, define S to be a d-dimensional
pointer.
It's possible in C to functionally represent an N dimensional array at run time, if not a pointer with an arbitrary number of levels of indirection. This could be a start (uncompiled, and this utterly ignores any possible alignment issues):
void *allocateArray( unsigned int N, size_t elemSize, unsigned int *dimensions )
{
if ( N == 1U )
{
return( malloc( elemSize * dimensions[ 0 ] ) )
}
void *array = malloc( sizeof( void * ) * dimensions[ 0 ] );
for ( unsigned ii = 0; ii < dimensions[ 0 ]; ii++ )
{
array[ ii ] = allocateArray( N - 1, elemSize, &( dimensions[ 1 ] ) );
}
return( array );
}
Note, that is not a very efficient way of allocating an N-dimensional array.
You could call it like this:
unsigned dims[] = { 5,7,8,9 };
unsigned d = sizeof( dims ) / sizeof( dims[ 0 ] );
size_t elemSize = sizeof( double );
void *array = allocateArray( d, elemSize, dims );
A varargs solution is probably possible, too.
Dereferencing the array would require something similar. This returns the address of the element dereferenced:
void *dereferenceArray( void *array, unsigned int N,
size_t elemSize, unsigned int *element )
{
if ( N == 1U )
{
char *tmp = array;
return( tmp + ( elemSize * element[ 0 ] ) );
}
else
{
void **tmp = array;
return( dereferenceArray( tmp[ element[ 0 ] ],
N - 1, elemSize, &( element[ 1 ] ) ) );
}
}
It'd be much easier in C++ as you could provide a [] operator to your array object and nest them to build N-dimensional arrays.
You could create the runtime equivalent of a d-indirection pointer by chaining as many void ** pointers as you need. A sparse array could then be built this way:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 4)
{
printf("Call this passing d (dimensions), n (elements for each dim), u (used elements) as parameters\n");
return 0;
}
int d = atoi(argv[1]);
assert(d > 0);
int n = atoi(argv[2]);
assert(n > 0);
int u = atoi(argv[3]);
assert(u < n * d);
// Creating
void *root = malloc(sizeof(void *) * n);
memset(root, 0, sizeof(void *) * n);
srand(time(NULL));
int i, p, c;
void **cursor;
for (int c = 0; c < u; ++c)
{
cursor = root;
for (i = 0; i < d; ++i)
{
p = rand() % n;
if (cursor[p] == NULL)
{
cursor[p] = malloc(sizeof(void *) * n);
memset(cursor[p], 0, sizeof(void *) * n);
}
cursor = cursor[p];
}
p = rand() % n;
if (cursor[p] == NULL)
cursor[p] = "Hello";
else
--c;
}
// Traversing
struct SE
{
void * *s;
int p;
};
struct SE *stack = malloc(sizeof(struct SE) * (d + 1));
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
}
else if (cursor[p] != NULL)
{
if (i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
else
{
printf("root");
for (c = 0; c < i; ++c)
printf("[%d]->", stack[c].p);
printf("[%d]=\"%s\"\n", p, cursor[p]);
}
}
}
// Tearing down
for (cursor = root, p = 0, i = 0; ; ++p)
{
if (p == n)
{
if (i == 0)
break;
cursor = stack[--i].s;
p = stack[i].p;
free(cursor[p]);
}
else if (cursor[p] != NULL && i < d)
{
stack[i].s = cursor;
stack[i++].p = p;
cursor = cursor[p];
p = -1;
}
}
free(root);
free(stack);
return 0;
}

How to allocate and declare a 3D of array of structs in C?

How do you allocate and declare a 3D array of structs in C?
Do you first allocate the array or declare it?
I feel like you have to allocate it first so you can declare it so it is on the heap, but then how do you allocate something that hasn't been made yet?
Also, should you allocate it all at once or element by element?
Also am i putting the structs into the array correctly?
My guess on how to do it would be:
header.h
struct myStruct{
int a;
int b;
};
typedef struct myStruct myStruct_t;
main.c
#include "header.h"
#include <stdio.h>
#include <stdlib.h>
int main(void){
int length=2;
int height=3;
int width =4;
myStruct_t *elements;
struct myStruct arr = (*myStruct_t) calloc(length*height*width, sizeof(myStruct);
//zero based array
arr[length-1][height-1][width-1];
int x=0;
while(x<length){
int y=0;
while(y<height){
int z=0;
while(z<depth){
arr[x][y][z].a=rand();
arr[x][y][z].b=rand();
z++;
}
y++;
}
x++;
}
return 0;
}
The easy way is:
myStruct_t (*arr2)[height][width] = calloc( length * sizeof *arr );
Then your loop can access arr2[x][y][z].a = rand(); and so on. If you're not familiar with this way of calling calloc, see here. As usual with malloc, check arr2 against NULL before proceeding.
The triple-pointer approach is not really a practical solution. If your compiler does not support variably-modified types then the array should be flattened to 1-D.
There are a couple of different ways to do this, depending on what you want. First, you can allocate your array on the stack (in C99 and some compilers) like this:
myStruct_t arr[length][height][depth];
If you want it allocated on the heap, then you can do a single allocation of the appropriate size. You can then either do the index calculation yourself or make a pointer do the work for you (in C99 and some compilers):
void *buf = malloc(length * height * width * sizeof(myStruct_t));
myStruct_t *arr = buf;
myStruct_t (*arr2)[height][width] = buf;
/* TODO: check return of malloc */
...
arr[x * height * width + y * width + z].a = rand(); /* indexing the C89 way */
arr2[x][y][z].b = rand(); /* indexing the C99 way */
Or you can manually allocate the multiple dimensions.
#include <stddef.h>
#include <stdlib.h>
typedef struct myStruct
{
int a, b;
} myStruct_t;
int main()
{
myStruct_t ***arr;
int length = 5000, height = 1000, depth = 20;
int x, y, z;
int ret = 1;
if (NULL == (arr = malloc(length * sizeof(myStruct_t**))))
goto FAIL;
for (x = 0; x < length; ++x)
{
if (NULL == (arr[x] = malloc(height * sizeof(myStruct_t*))))
goto FAIL_X;
for (y = 0; y < height; ++y)
{
if (NULL == (arr[x][y] = malloc(depth * sizeof(myStruct_t))))
goto FAIL_Y;
for (z = 0; z < depth; ++z)
{
arr[x][y][z].a = rand();
arr[x][y][z].b = rand();
}
}
}
/* TODO: rest of program logic */
/* program successfully completed */
ret = 0;
/* reclaim arr */
FAIL_CLEANUP: /* label used by TODO code that fails */
for (x = length - 1; x >= 0; --x)
{
for (y = height - 1; y >= 0; --y)
{
free(arr[x][y]);
FAIL_Y:
;
}
free(arr[x]);
FAIL_X:
;
}
free(arr);
FAIL:
return ret;
}
This last version uses a lot more memory for all the explicit pointers it contains, its memory locality is worse and it's significantly more complex to properly allocate and reclaim. However, it does allow different sizes along your dimensions. For example, the array arr[0][4] can have a different size than arr[0][7] if you ever need that.
If you want to allocate it on the heap, then you probably want the second version with a single allocation and multi-dimension pointer (if available) or do the indexing yourself manually using appropriate math.

Multithreading in C, get the average of 4 arrays

I'm new to multithreading had my first lesson yesterday. So I've wrote a program to get the average of 4 big arrays , each array is a thread and the main waits for all the threads and gives the average of the 4 arrays. This is possible because each thread gives the average of one array. The array is just a headerfile with a float array.
It compiles but gives me a segmentation error and I don't see why.
#include "gemiddelde.h"
#include <stdlib.h>
#include <stdio.h>
float *gemiddelde(void *arg)
{
float *a;
int i;
a = (float *)arg;
float * som;
for( i = 0; i < 100000; i++)
*som += a[i];
*som = *som / 100000;
return som;
}
int main()
{
pthread_t t1,t2,t3,t4;
float * som1, * som2, * som3, * som4, *result;
pthread_create(&t1,NULL,gemiddelde,a1);
pthread_create(&t2,NULL,gemiddelde,a2);
pthread_create(&t3,NULL,gemiddelde,a3);
pthread_create(&t4,NULL,gemiddelde,a4);
pthread_join(t1,som1);
pthread_join(t2,som2);
pthread_join(t3,som3);
pthread_join(t4,som4);
usleep(1);
*result = *som1 + *som2 + *som3 + *som4;
printf("Gemiddelde is: %f ", *result);
return 0;
}
Can someone help me?
Kind regards,
In
*result = *som1 + *som2 + *som3 + *som4;
result is used unitialized. Make it a plain float instead of a pointer.
From your current code, segfault occurs because som* aren't initialized -- they are dangling pointers.
Your code is very problematic, because the thread code requires memory to store the result, and as it stands your code is plain wrong because it doesn't have any memory and just dereferences a dangling pointer. But even allocating memory inside the thread is not a great idea, because it's not clear who is responsible for it and who will clean it up. So it's much better to allocate all your required memory in the main function. First some boiler plate to set up the thread argument data:
typedef struct thread_arg_type_
{
float * data;
size_t len;
float retval;
} thread_arg_type;
thread_arg_type * create_thread_arg(size_t n)
{
thread_arg_type * result = malloc(sizeof(thread_arg_type));
if (!result) return NULL;
float * const p = malloc(n * sizeof(float));
if (!p)
{
free(result);
return NULL;
}
result->len = n;
result->data = p;
return result;
}
void free_thread_arg(thred_arg_type * r)
{
if (r) free(r->data);
free(r);
}
Now here's how we use it:
int main()
{
thread_arg_type * arg;
pthread_t t;
arg = create_thread_arg(array1_size);
pthread_create(&t, NULL, getmiddle, arg);
// ...
pthread_join(t, NULL);
printf("The result is: %f.\n", arg->retval);
free_thread_arg(arg);
}
And finally we must adapt getmiddle:
void * getmiddle(thread_arg_t * arg)
{
arg->retval = 0;
for(unsigned int i = 0; i != arg->len; ++i)
arg->retval += arg->data[i];
arg->retval /= arg->len;
return NULL;
}

C: Accessing a pointer from outside a function

I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.

Resources