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.
Related
I am trying to learn how to create a function that will take a dynamic int array (int arrayPtr = (int) malloc...) and replace it with another dynamic array. This new array will not simply be of different values, but potentially a different number of elements.
From my research, I've learned that I need to pass into this function a reference to my array pointer, rather than the pointer itself (&arrayPtr). That means the function signature needs to have int **arrayPtr instead of int *arrayPtr.
I feel like it makes sense to me; We need to tell arrayPtr to point to a different location in memory, so we need the memory address of arrayPtr rather than its value (the memory address of the original array);
I wrote a little test program to see if I understood, but I cannot get it to work. Using debugging, I've observed the following: From within the function, the (int **arrayPtr) doesn't represent the entire array, but just the first element. That is, I can get the value 500 if I do *arrayPtr[0], but *arrayPtr[1] is inaccessible memory.
Here is my test program:
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = (int *)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = *arrayPtr[i] * 2;
}
free(arrayPtr);
arrayPtr = &tempArrayPtr;
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = (int*)malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
The function is supposed create a new array with the value of each element of the original array doubled, and have the arrayPtr variable in the calling function refer to the new array instead. As i have written it, however, it gets SIGSEGV when the replaceArray function tries to access *arrayPtr[1].
I realize that this little demonstration program is not doing anything that requires the behavior that I'm testing. It is just so that I can understand the concept with a simple example.
Since this is a tiny, trivial, program, I feel justified in that the answer that I accept will contain the complete working version of this code.
There have to be three changes in you code:
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength);
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;//In this if you use the without braces it will acts array of pointers that is pointing to a array. So we have to get the value from that using that braces.
}
free(*arrayPtr);//<< here we have to free the memory of arrayPtr not the address of the &arrayPtr.
*arrayPtr = tempArrayPtr; // Here you have to assign the address to that value of arrayPtr.
return;
}
There is no need the type cast the return value of malloc.
Both of these lines are wrong:
free(arrayPtr);
arrayPtr = &tempArrayPtr;
The first line passes the address of your variable to free(), rather than the address of the actual allocated array. Since the variable is on the stack rather than mallocated, free() will crash or abort here. What you want to do instead is free(*arrayPtr):.
The second line merely sets the local variable arrayPtr to the address of the variable tempArrayPtr. What you want to do instead is *arrayPtr = tempArrayPtr;.
See the below code and the inline comments.
#include <stdlib.h>
void replaceArray(int **arrayPtr, unsigned int arrayLength) {
int i;
int *tempArrayPtr;
tempArrayPtr = malloc(sizeof(int) * arrayLength); //do not cast
for (i = 0; i < arrayLength; ++i) {
tempArrayPtr[i] = (*arrayPtr)[i] * 2;
}
free(*arrayPtr); // free the *arrayPtr, [which is `arrayPtr` from `main`]
*arrayPtr = tempArrayPtr; //copy tempArrayPtr and put it into *arrayPtr
return;
}
int main(int argc, char **argv) {
int i;
int arrayLength = 2;
int *arrayPtr;
arrayPtr = malloc(sizeof(int) * arrayLength); // do not cast
for (i = 0; i < arrayLength; ++i) {
arrayPtr[i] = i + 500;
}
replaceArray(&arrayPtr, arrayLength);
exit(EXIT_SUCCESS);
}
I'm a java student who's currently learning about pointers and C.
I tried to make a simple palindrome tester in C using a single array and pointer arithmetic.
I got it to work without a loop (example for an array of size 10 :*(test) == *(test+9) was true.
Having trouble with my loop. School me!
#include<stdio.h>
//function declaration
//int palindrome(int *test);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
int *ptr;
ptr = &numArray[0];
output = palindrome(ptr);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test) {
int i;
for (i = 0; i <= (sizeof(test) / 2); i++) {
if (*(test + i) == *(test + (sizeof(test) - i)))
return 1;
else
return 0;
}
}
The Name of the array will itself acts as a pointer to an first element of the array, if you loose the pointer then there is no means for you to access the element of the array and hence you can send just the name of the array as a parameter to the function.
In the palindrome function:
you have used sizeof(test)/2. what happens is the address gets divided which is meaningless and hence you should not use that to calculate the mid element.
sizeof the pointer will be the same irrespective of the type of address that gets stored.
Why do you copy your pointer in another variable?
int *ptr;
ptr = &numArray[0];
Just send it to you function:
palindrome(numArray);
And sizeof(test) give you the memory size of a pointer, it's not what you want. You have to give the size in parameter of your function.
int palindrome(int *test, int size){
...
}
Finally your code must look like this:
#include<stdio.h>
int palindrome(int *test, int size);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
output = palindrome(numArray, 10);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test, int size) {
int i;
for (i = 0; i < size / 2; i++) {
if (*(test + i) != *(test + (size - 1) - i))
return 0;
}
return 1;
}
This question already has answers here:
Returning Arrays/Pointers from a function
(7 answers)
Closed 9 years ago.
Here is my code:
int *myFunction()
{
int A[3] = {1,2,3};
return A; //this will return the pointer to the first element in the array A
}
int main (void)
{
int A[3];
A = myfunction(); //A gets the return value of myFunction
for(int j=0; j==2; j++)
{
B[j] = 2* A[j]; //doubles each value in the array
}
printf("%d",B);
return 0;
}
But this does not work because the A that is returned is not the actual vector. How do I get the actual vector {1,2,3} in the main function?
The function myFunction allocates A, but this allocation only exists within the scope of the function. When the function returns the memory holding A is destroyed. This means that the function is returning a pointer to memory that has not been un-allocated.
The problem is that the variable A does not persist outside the function. You could use a global variable or pass a pointer to the buffer into myFunction
Global variable method:
static int A[3];
int* myFunction()
{
A[0] = 1; A[1] = 2; //etc
return A;
}
In this example, because A is a global, the memory pointed to by A persists throught your program's entire life time. Therefore it is safe to return a pointer to it...
As a side note, global variables should probably not be used in this way... it's a little clunky. The use of the static keyword means that A will not be accessible outside of this module (C file).
Pointer method:
void myFunction(a[3])
{
a[0] = 1; a[1] = 2; //etc
}
int main()
{
myA[3];
myFunction(myA);
// and continue to print array...
}
In this example the main() function allocates myA. This variable exists whilst the function is executing (it's an automatic variable). A pointer to the array is passed into the function, which fills the array. Therefore the main() function can get information from myFunction().
Another way to make the variable myA persist would be to allocate it on the heap. To do this you would do something like int *myA = malloc(sizeof(int) * NUMBER_OF_INTS_IN_ARRAY. This memory will then persist until you specifically desctroy it using free() or you program ends.
int A[3] = {1,2,3}; is being created on the stack, this is, it is a local array and it's memory can be used again after myFunction executes. You have to either make int A[3] static within myFunction or by placing it outside of all functions. Another option would be to create int A[3] within main and pass the address of A to myFunction so myFunction can directly modify the contents of A.
As is, your code isn't close to working anyway... your for loop is broken, you have undefined variables in main, you have function name mismatches, and your print isn't going to do what you want anyway...
The big problem as that you've got undefined behavior going on, you can't access A[] outside of the function where it was locally defined. The easiest way to rectify that is to use dynamic memory, malloc() some memory for A in your myFunction then use the values in main and free() the memory when you're done.
Here's the example fixing your other syntax issues:
int *myFunction()
{
int *A;
A = malloc(3 * sizeof(int));
A[0] = 1;
A[1] = 2;
A[2] = 3;
return A;
}
int main (void)
{
int *A = myFunction(); //A gets the return value of myFunction
int B[3] = {0, 0, 0};
int j;
for(j=0; j<3; j++)
{
B[j] = 2* A[j]; //doubles each value in the array
}
free(A);
printf("%d",B[0]);
return 0;
}
Pass the array to be filled as argument to the initisliser function along with its size:
size_t myFunction(int * A, size_t s)
{
int A_tmp[3] = {1,2,3};
size_t i = 0;
for (; i < s && i < sizeof(A_tmp)/sizeof(A_tmp[0]); ++i)
{
A[i] = A_tmp[i];
}
return i;
}
Then call it like so:
int main()
{
int myA[3];
size_t s = sizeof(myA)/sizeof(myA[0]);
size_t n = myFunction(myA, s);
if (n < s)
fprintf(stderr, "Caution: Only the first %zu of %zu elements of A were initialised.\n", n, s);
// and continue to print array...
}
#include <stdio.h>
int (*myFunction(void))[3]
{
static int A[3] = {1,2,3};
return &A;
}
int main (void){
int (*A)[3], B[3];
A = myFunction();
for(int j=0; j<=2; j++)
{
B[j] = 2 * (*A)[j];
}
for(int j=0; j<3;++j)
printf("%d ", B[j]);
return 0;
}
I want to make a function pointer array and be able to call them in a for-loop. How can I achieve this? I have tried:
void (**a) (int);
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0]();
(*a[0])(); // Neither does work
}
But I am missing some syntax I guess:
error: too few arguments to function ‘*(a + (long unsigned int)((long unsigned int)i * 8ul))’
The function you declare is expected to take an int as a parameter:
a[0](1);
Also note that you declare a pointer to pointer for the functions, but you don't allocate any memory for them (I assume this is only in the example) Otherwise it should probably be:
void (*a[3]) (int);
You are declaring that a is a pointer to a pointer to (or an array of pointers to) a function that takes an int as a parameter - so you need to pass an int when you call the functions, e.g. a[0](42);.
I guess the below code is what you need.
typedef void * func_pointer(int);
func_pointer fparr[10];
for(int i = 0; i<10; i++)
{
fparr[i](arg); //pass the integer argument here
}
1) Where have you allocated or defined array to store function addresses?
2) in loop you are always calling (*a[0])();,There should be loop counter
You forgot to give an argument to your function.
void (**a) (int); // here it takes an int argument
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for ( i = 0; i < 3; i++){
a[0](); // here you do not give an argument
}
But be careful, you do not allocate memory to your a array, and it fails with a nice segmentation fault error.
void my_func1(int i) {
;
}
void my_func2(int i) {
;
}
void my_func3(int i) {
;
}
int main() {
void (**a) (int);
a = malloc(3*sizeof(void*)); // allocate array !
a[0] = &my_func1;
a[1] = &my_func2;
a[2] = &my_func3;
for (int i = 0; i < 3; i++){
a[i](1); // respect your own function signature
}
free(a); // it's always a good habit to free the memory you take
return 0;
}
You can typedef void (*pfun)(int); and then pfun a[3]; is the array you want.
The following code may work for you:
typedef void (*pfun)(int);
int main() {
pfun a[3];
a[0] = myfunc1; // or &myfunc1 whatever you like
a[1] = myfunc2;
a[2] = myfunc3;
}
You can define your function-array with the needed size and initialize it with your functions like:
void my_func1(int x){}
void my_func2(int x){}
void my_func3(int x){}
void (*a[])(int)={my_func1,my_func2,my_func3};
int i;
for(i=0;i<sizeof a/sizeof*a;++i)
a[i](i);
The address-operator '&' before any function-name is redundant.
I have function, it receive pointer to array and pointer to function and should return new array with order defined by function passed in parameter.
My problem how I copy element of one array to another without knowing its type
void * scrambleArr(void * arr, int numElem, int elemSize, int (*func)(void*)) {
void * newArr;
int cPos, newPos,i;
newArr = (void *)malloc(numElem*elemSize);
for (i=0 ; i < numElem ; i++)
{
cPos = i*elemSize;
newPos = func((char*)arr+cPos);
*((char*)newArr+newPos) = *((char*)arr+cPos);
}
return newArr;
}
Function that passed in the last parameter
int posArrayBySize(void *el) {
ARRAY* arr = (ARRAY *)el;
return arr->size - 1;
}
And code in main:
int main( ) {
ARRAY * arrSorted;
int a[2] = {1,2};
int b[3] = {1,1,1};
int c[1] = {9};
int d[4] = {3,3,3,3};
ARRAY arr[4] = {{a,2},{b,3},{c,1},{d,4}};
arrSorted =(ARRAY *)scrambleArr(arr,4,sizeof(ARRAY),posArrayBySize);
free(arrSorted);
return 0;
}
After running arrSorted contain garbage,
Can someone point me, what i miss?
Another option for me is not to copy, just to point one array to elements of other, is it possible?
Thanks.
memcpy is the function you are looking for.
This won't work
*((char*)newArr+newPos) = *((char*)arr+cPos);
because you're dereferencing arr+cPos as it is char, so it will copy only the first byte.