So I was playing around with some pointer today and ran into a rather confusing predicament. I use C a lot but couldn't seem to figure out why this wouldn't work maybe its just one of those days.
#include <stdio.h>
#include <stdlib.h>
void subr(int* numero){
int* newNum = malloc(sizeof(int));
(*newNum) = 5;
numero = newNum;
printf("%d\n", *numero);
}
int main(){
int* number;
printf("%p\n", (void *) number);
subr(number);
if(number == NULL)
printf("Not assigned\n");
else
printf("%d\n", *number);
}
So I create a pointer in main, pass it into a function which allocates space and then assigns it back to the pointer passed in. Why is it that everytime I run this I get that the pointer is still null?
The reason that this code does not work is that C is a pass-by-value language. If you wish to modify anything, you have to pass a pointer to it:
void subr(int** numero){
int* newNum = malloc(sizeof(int));
(*newNum) = 5;
*numero = newNum;
printf("%d\n", **numero);
}
int main(){
int* number = NULL; // <<== Need to initialize it
printf("%p\n", (void *) number);
subr(&number);
if(number == NULL)
printf("Not assigned\n");
else
printf("%d\n", *number);
free(number); // <<== Don't forget to free what's malloc-ed
}
Related
I feel as though this shouldn't be such a hard problem and I've tried everything that I've found on similar questions to no avail, so I thought I'd give it a try to ask myself. My code (simplified) is as follows:
#include <stdio.h>
#include <stdlib.h>
void setArraySize(int** arr) {
int arrSize;
printf("\nEnter array size: ");
scanf("%d", &arrSize);
int* tmp = realloc(*arr, arrSize);
if (tmp == NULL) {
printf("Error");
return;
}
*arr = tmp;
}
void auswahl() {
int* arr = NULL;
setArraySize(&arr);
free(arr);
}
int main() {
auswahl();
return 0;
}
When debugging I noticed that my array only contains the integer -842150451. I am using Microsoft Visual Studios 2019 Community. Additionally, even when trying the most basic and safest functions, I attain the same result. Could the problem then have to do with Visual Studios?
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
int* tmp = realloc(*data, 20);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
}
int main() {
int* arr = NULL;
increase(&arr);
printf("%d", sizeof(arr));
return 0;
}
Thanks in advance for any help!
I changed your second code a little bit (added printf's), it will help you understand what is happening
#include <stdio.h>
#include <stdlib.h>
void increase(int** data)
{
printf ("in increase|*data|%p|\n", *data);
int* tmp = realloc(*data, 20);
printf ("in increase|*data after realloc|%p|\n", *data);
printf ("in increase|tmp after realloc|%p|\n", tmp);
if (tmp == NULL) {
printf("Error");
return;
}
*data = tmp;
printf ("in increase|*data after assign|%p|\n", *data);
}
int main() {
int* arr = NULL;
printf ("in main|arr|%p|\n", arr);
printf ("in main|arr size|%d|\n", sizeof(arr));
increase(&arr);
printf ("in main|arr after increase|%p|\n", arr);
printf ("in main|arr size after increase|%d|\n", sizeof(arr));
return 0;
}
this will output this :
in main|arr|(nil)|
in main|arr size|8|
in increase|*data|(nil)|
in increase|*data after realloc|(nil)|
in increase|tmp after realloc|0x2441010|
in increase|*data after assign|0x2441010|
in main|arr after increase|0x2441010|
in main|arr size after increase|8|
So basically the size of arr doesn't change because it's not an array, it's a pointer to an int, the size here is 8 because it's a 64bits machine, and memory adresses for 64bits need 8 Bytes to be stored, and this is what sizeof() returns the size in bytes of the type you gave it ( int* arr a pointer to an int )
for the other values you can see that you have effectively allocated memory in the heap at address 0x2441010 so your QUOTE"array"QUOTE (it's not an array), starts at this address and have enough space for 20(BYTES) if you wanted 20 integers you should have used realloc(..., 20* sizeof(int)) because these alloc functions use bytes as their unit.
hope this helps you somehow.
I am trying to receive a number from the user.
And create an array with that number, but, inside a function.
Here are my few attempts, I get into run time errors.
Help is very much appreciated.
#include <stdio.h>
#include <stdlib.h>
int* Init(int* p, int num);
int main() {
int *p;
int num, i;
puts("Enter num of grades:");
scanf("%d", &num);
Init(&p, num);
//for (i = 0; i < num; i++)
//{
// scanf("%d", &p[i]);
//}
free(p);
}
int* Init(int* p, int num)
{
int *pp;
p = (int *)malloc(num*sizeof(int));
if (!pp)
{
printf("Cannot allocate memory\n");
return;
}
p = pp;
free(pp);
}
You have done well upto the point you understood you need to pass a pointer to pointer. But your function signature doesn't take an int **. Either you pass a pointer to pointer and store the allocated memory in it:
void Init(int **pp, int num)
{
int *p;
p = malloc(num*sizeof(int));
if (!p)
{
printf("Cannot allocate memory\n");
}
*pp = p;
}
And check if the Init() returns a proper pointer:
Init(&p, num);
if(p == NULL) {
/*Memory allocation failed */
}
Or allocate memory and return the pointer:
int* Init(int num)
{
int *p;
p = malloc(num*sizeof(int));
if (!p)
{
printf("Cannot allocate memory\n");
}
return p;
}
and from main() call as:
int * p = Init(num);
if(p == NULL) {
/*Memory allocation failed */
}
Change the prototype of Init() accordingly.
In any case, you must not free() the pointer in Init(). That just de-allocates memory immediately and you'll be left with a dangling pointer.
And you need to free() in the main() after you are done with it.
int *pp;
p = (int *)malloc(num*sizeof(int));
if (!pp) /* pp is used uninitialized at this point */
int *p;
int num, i;
puts("Enter num of grades:");
scanf("%d", &num);
Init(&p, num);
free(p); /* p is used uninitialized at this point */
If you want to allocate space for a pointer to int inside another function, you need to pass a pointer to pointer:
...
Init(&p, num);
...
int Init(int **pp, int num)
{
*pp = malloc(num * sizeof(int));
...
First you need to fix the prototype of your function. It should be
int* Init(int** p, int num);
Then fix the function definition
int* Init(int** p, int num)
{
//int *pp; // You don not need this variable
*p = malloc(num*sizeof(int)); // Allocate memory
if (!*p)
{
printf("Cannot allocate memory\n");
return NULL; // Return a NULL pointer
}
return *p;
}
Some typos in your code,
p = (int *)malloc(num * sizeof(int));
should be
pp = (int *)...
Your free(pp); is what is causing it to not work chiefly, you do not want to call that or the memory you allocated will not be saved. Also the memory of pp is essentially "lost" at the end of the function call as method parameter to Init p is a value copy not exact reference to main's version of p, thus when Init returns, the changes to p are 'lost'.
simply do: p = Init(); and in init return pp;
Exp:
This line p = pp, sets variable p to point to the memory allocated by pp, thus a free of pp is a free to p as well.
I am not sure if returning an address to memory is always considered good practice, as you have to ensure it is freed, but for your program it would work.
It's very important to know that your function doesn't modify your pointer (*p),The **p is lost And *p doesn't have a valid and known memory address in the Main function.
To allocate the memory safely I suggest these two functions.
void init(int **p,int number){
*p = malloc(number*sizeof(int));
}
If you want that your function returns the pointer allocated you can do this:
int* init(int number){
int* p = malloc(number*sizeof(int));
return p;
}
Alright I've been cranking away at this all day (not hw), and though it may not be a particularly useful bit of code, it is a neat conceptual thing. I am trying to figure out the best way to set a value at the end of, for lack of a better name, a pointer to pointer to pointer chain. For example, I declare:
int *****ptr;
What is the best way to set each pointer to pointer segment, all the way down to the actual int value?
This code doesn't compile because it doesn't like the way I use and dereference void pointers:
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(int argc, char **argv)
{
int *****number;
*****number = malloc(sizeof(void*));
void *ptr = *number;
int i;
for(i = 1; i < NUMPOINTERS; i++)
{
if(i == NUMPOINTERS - 1)
{
ptr = malloc(sizeof(int));
int *iPtr = (int*)ptr;
*iPtr = 900;
break;
}
*ptr = malloc(sizeof(void*));
ptr = **ptr;
}
printf("%d", *****number);
return 0;
}
Is there some article out there that talks about ridiculous numbers of pointers to pointers and how to work with them?
What you have is pretty close. You probably want to work from the inside out, though. Here's a complete example based on your program (comments inline):
#include <stdio.h>
#include <stdlib.h>
#define NUMPOINTERS 5
int main(void)
{
void *ptr = malloc(sizeof(int)); // allocate space for the integer value
*(int *)ptr = 900; // initialize it
// iterate to create the nested pointers
for (int i = 1; i < NUMPOINTERS; i++)
{
void **newptr = malloc(sizeof(void *)); // create a new pointer
*newptr = ptr; // point it at what we have so far
ptr = newptr; // "step out" one level
}
int *****number = ptr; // make our 'int *****' pointer
printf("%d\n", *****number); // dereference and print the pointed-to value
return 0;
}
I want to convert the type of the pointer 'p'. Begining ,the type of the pointer p is void .After allocating four bytes of memory for it, I cast pointer type into 'int',However ,this doesn't work . maybe the sentence p=(int *)p doesn't work.
Please tell me why and solve the problem.thanks.
The coding:
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
void *p;
p=malloc(sizeof(int));
if(p == NULL)
{
perror("fail to malloc");
exit(1);
}
p=(int *)p;
*p=100;
printf("the value is : %d\n",*p);
return 0;
}
You'll have an easier time directly casting the void pointer returned by malloc to an int*
#include<stdio.h>
#include <stdlib.h>
int main(void)
{
int *p;
p = malloc(sizeof(int));
if(p == NULL)
{
perror("fail to malloc");
exit(1);
}
*p=100;
printf("the value is : %d\n",*p);
return 0;
}
You can't change a variable's type after you have declared it. For what you are asking, you need to declare a separate int* variable and assign your p variable to it with the type-cast:
int *i = (int *)p;
*i = 100;
printf("the value is : %d\n", *i);
Or, simply declare p as a int* to begin with and then type-cast the pointer returned by malloc(), like #GWW showed.
You cant change a variables type, you can do a type cast but that is only temporary.
what you want would be something like *(int*)p = 100;
printf("the value is : %d\n", *(int*)p);
You can't. But you can create a new pointer to int and point to that position, like:
void *p;
p= malloc...
int *pi;
pi= p;
*pi= 25;
This is one of those annoying things where you know the answer is easy, but you just can't see it.
The printf statement in AllocIntArray shows that arrayPtr is correctly being assigned a memory location, however when the printf statement in main is run, it shows arrayB is still set to NULL.
Can someone show me what I am doing wrong when passing in arrayB to AllocIntArray?
#include <stdio.h>
#include <stdlib.h>
void AllocIntArray(int *arrayPtr, int numElements);
int main()
{
int *arrayB = NULL;
AllocIntArray(arrayB, 10);
printf("Pointer: %p\n", arrayB);
free(arrayB);
getchar();
return EXIT_SUCCESS;
}
void AllocIntArray(int *arrayPtr, int numElements)
{
arrayPtr = (int *)malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", arrayPtr);
if(arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
}
Pass the double pointer.
#include <stdio.h>
#include <stdlib.h>
void AllocIntArray(int **arrayPtr, int numElements);
int main()
{
int *arrayB = NULL;
AllocIntArray(&arrayB, 10);
printf("Pointer: %p\n", arrayB);
free(arrayB);
getchar();
return EXIT_SUCCESS;
}
void AllocIntArray(int **arrayPtr, int numElements)
{
*arrayPtr = malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", *arrayPtr);
if(*arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
}
That's because arrayB is passed to AllocIntArray by value. Either pass it by reference (with a pointer-to-pointer), or better, return it from AllocIntArray:
int *AllocIntArray(int numElements)
{
int *arrayPtr = malloc(sizeof(int) * numElements);
printf("Pointer: %p\n", arrayPtr);
if(arrayPtr == NULL)
{
fprintf(stderr, "\nError allocating memory using malloc");
exit(EXIT_FAILURE);
}
return arrayPtr;
}
You need to brush up a bit on parameter passing to functions.
The pointer you are sending to AllocIntArray is being copied into arrayPtr, The line
arrayPtr = (int *)malloc(sizeof(int) * numElements);
assigns a value into the copy, and not the original variable, and therefore the original variable still points to nowhere.
First solution that comes to mind is to send a pointer to that pointer, but I think you'd best do some general brushing up on the matter of parameter passing before going much further.
arrayPtr is a pointer and the pointer is passed by value to the parameter. AllocIntArray can modify its version of arrayPtr but the changes won't be seen by main().
(Edit: if you're using C++) modifying the signature for AllocIntArray to change the type of arrayPtr to a reference ought to fix your problem.
void AllocIntArray(int *&arrayPtr, int numElements)
The basic problem here is you are passing arrayB to AllocIntArray function as passed by value .In AllocIntArray its allocating memory properly and arrayptr is valid but in main function its not the same memory which you are expecting .
This is the basic C programming concept and you can check bu adding print in both the function .
EX: I am sharing the difference between both problem and success case with below example .
/*Code with passed by value as a parameter*/
#include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int *arrayptr,int numElements)
{
arrayptr = (int*) malloc(sizeof(int)*numElements);
printf("Inside _func_AllocateIntarray_pointer:%p\n",arrayptr);
if(arrayptr == NULL)
{
printf("ERR_MEM_ALLOCATION_FAILED:\n");
}
}
int main()
{
int *arrayB = NULL;
AllocateIntarray(arrayB,10);
printf("Inside _func_mainPointer:%p\n",arrayB);
free(arrayB);
return 0;
}
/*Output :
Inside _func_AllocateIntarray_pointer:0x55be51f96260
Inside _func_mainPointer:(nil)*/
Code with Passed by reference and using double pointer .
#include<stdio.h>
#include<stdlib.h>
void AllocateIntarray(int **arrayptr,int numElements)
{
*arrayptr = malloc(sizeof(int)*numElements);
printf("Inside _func_AllocateIntarray_pointer:%p\n",*arrayptr);
if(*arrayptr == NULL)
{
printf("ERR_MEM_ALLOCATION_FAILED:\n");
}
}
int main()
{
int *arrayB = NULL;
AllocateIntarray(&arrayB,10);
printf("Inside _func_mainPointer:%p\n",arrayB);
free(arrayB);
return 0;
}
/*Output :
Inside _func_AllocateIntarray_pointer:0x562bacd1f260
Inside _func_mainPointer:0x562bacd1f260*/