Should every pointer in C be allocated on the heap? - c

Is it required, or recommended, that every pointer in C be allocated on the heap? For example, is it likely or possible that the following code could produce a segmentation fault?
#include <stdio.h>
int main(void) {
int* p;
*p = 16;
printf("Pointer p = %d\n", *p);
return 0;
}

This code will likely segfault because p is uninitialized and therefore doesn't point to a valid address.
A pointer doesn't necessarily have to point to heap memory. It just needs to point to a valid object. For example:
int x = 4;
int *p = &x;
*p = 5;
printf("x=%d\n", x); // prints 5

It doesn't have to be allocated. You just need to make sure it points to valid memory address, which you didn't in your example.
Since you didn't initialize the pointer, it has some random value and trying to dereference it will interpret this value as a memory address, which is probably going to give you a segmentation fault.
You could instead do something like:
int x; // not initialized, random value in memory
int *p = &x;
*p = 16; //now you are accessing a valid address (x's)

Related

Return pointer from a function without defining the variable as static?

#include <stdio.h>
#include <stdlib.h>
int* func();
int main(void) {
int *b = NULL,i;
b = func();
for(i=0;i<7;i++)
{
printf("%d\n",*b);
b++;
}
}
int * func()
{
int *p;
p = malloc(sizeof(int) * 7);
int arr[]={1,2,3,4,5,6,7}; //without using static
p = arr;
return p;
}
How to return the address of the array to the main function for printing the values ?? Without declaring the array as static if we allocate memory for the array in heap then can we able to pass the array to the function as a pointer ??
You are close, but not quite there.
The following expressing causes p to point to arr's address which is not the intended effect:
p = arr;
Remember, p is a pointer, and if you do not use the dereference operator *, then you are refering to the pointer's address rather than its value. arr's memory is deallocated when the function exits, and the memory malloc'd to p is lost because you reassigned the address of p to point to the address of the local variable arr.
The solution is to copy the values of arr to p using a for loop:
int i = 0;
for (; i < 7; ++i) {
p[i] = arr[i];
}
This will print the desired result because you replaced the values of what p pointed to rather than the address of p itself.
You can't. The array is gone when you leave the function, any pointer to the array would have an undeterminate value when you leave the function, and using such a pointer in any way invokes undefined behaviour.
Your malloc () call is pointless and leads to a memory leak, because you allocate space for 7 ints on the heap, and then overwrite the pointer, so the memory can never be used or freed.

Segmentation Fault with c pointer

I have a segmentation fault with the following code and i really don't understand where the issue is...
int *p;
p[0]=1;
printf("%d\n",*p);
Thanks
p is uninitialized. p[0] (equivalent to *(p + 0), which is effectively *p) attempts to dereference it, which results in undefined behavior due to the indeterminate value in p.
To make the program well-defined you need to make it point to some allocated memory location:
int i;
int* p = &i;
p[0] = 1;
printf("%d\n", *p);
p is not initialized. You need to initialize it first before dereferencing, otherwise it will lead to undefined behavior.
int *p; // p is pointing to a random location in memory
int a;
p = &a; // p is pointing to the variable a
p[0] = 1;
int *p;
p is an uninitialized pointer and may point to any unauthorized memory and with the below statement you tend to write to some invalid memory -
p[0]=1;
You can allocate memory to do so -
int *p=malloc(sizeof(int));
if(p!=NULL){
p[0]=1;
printf("%d",p[0]);
}
free(p);

Array Pointers vs Regular Pointers in C

I am a total beginner to C so please, work with my ignorance. Why does a normal pointer
int* ptr = &a; has two spaces in memory (one for the pointer variable and one for the value it points to) and an array pointer int a[] = {5}; only has one memory space (if I print out
printf("\n%p\n", a) I get the same address as if I printed out: printf("\n%p\n", &a).
The question is, shouldn't there be a memory space for the pointer variable a and one for its value which points to the first array element? It does it with the regular pointer int* ptr = &a;
It's a little unclear from your question (and assuming no compiler optimization), but if you first declare a variable and then a pointer to that variable,
int a = 4;
int *p = &a;
then you have two different variables, it makes sense that there are two memory slots. You might change p to point to something else, and still want to refer to a later
int a = 4;
int b = 5;
int *p = &a; // p points to a
// ...
p = &b; // now p points to b
a = 6; // but you can still use a
The array declaration just allocates memory on the stack. If you wanted to do the same with a pointer, on the heap, you would use something like malloc or calloc (or new in c++)
int *p = (int*)malloc(1 * sizeof(int));
*p = 4;
but of course remember to free it later (delete in c++)
free(p);
p = 0;
The main misunderstanding here is that &a return not pointer to pointer as it expected that's because in C language there some difference between [] and * (Explanation here: Difference between [] and *)
If you try to &a if a was an pointer (e.g. int *a) then you obtain a new memory place but when your use a static array (i.e. int a[]) then it return address of the first array element. I'll also try to clarify this by mean of the next code block.
#include <stdio.h>
int main(int argc, char *argv[])
{
// for cycles
int k;
printf("That is a pointer case:\n");
// Allocate memory for 4 bytes (one int is four bytes on x86 platform,
// can be differ for microcontroller e.g.)
int c = 0xDEADBEEF;
unsigned char *b = (unsigned char*) &c;
printf("Value c: %p\n", c);
printf("Pointer to c: %p\n", &c);
printf("Pointer b (eq. to c): %p\n", b);
// Reverse order (little-endian in case of x86)
for (k = 0; k < 4; k++)
printf("b[%d] = 0x%02X\n", k, b[k]);
// MAIN DIFFERENCE HERE: (see below)
unsigned char **p_b = &b;
// And now if we use & one more we obtain pointer to the pointer
// 0xDEADBEEF <-- b <-- &p_b
// This pointer different then b itself
printf("Pointer to the pointer b: %p\n", p_b);
printf("\nOther case, now we use array that defined by []:\n");
int a[] = {5,1};
int *ptr = &a;
// 'a' is array but physically it also pointer to location
// logically it's treat differ other then real pointer
printf("'a' is array: %x\n", a);
// MAIN DIFFERENCE HERE: we obtain not a pointer to pointer
printf("Pointer to 'a' result also 'a'%x\n", &a);
printf("Same as 'a': %x\n", ptr);
printf("Access to memory that 'a' pointes to: \n%x\n", *a);
return 0;
}
This is very simple. In first case,
int* ptr = &a;
you have one variable a already declared and hence present in memory. Now you declare another variable ptr (to hold the address, in C variables which hold address of another variable are called pointers), which again requires memory in the same way as a required.
In second case,
int a[] = {5};
You just declare one variable (which will hold a collection of ints), hence memory is allocated accordingly for a[].
In this expression, int* p = &a; p has only one memory location, of the WORD size of your CPU, most probably, and it is to store the address (memory location) of another variable.
When you do *p you are dereferencing p, which means you are getting the value of what p points to. In this particular case that would be the value of a. a has its own location in memory, and p only points to it, but does not itself store as content.
When you have an array, like int a[] = {5};, you have a series (or one) of memory locations, and they are filled with values. These are actual locations.
Arrays in C can decay to a pointer, so when you printf like you did with your array, you get the same address, whether you do a or &a. This is because of array to pointer decay.
a is still the same location, and is only that location. &a actually returns a pointer to a, but that pointer sits else where in memory. If you did int* b = &a; then b here would not have the same location as a, however, it would point to a.
ptr is a variable containing a memory address. You can assign various memory addresses to ptr. a is a constant representing a fixed memory address of the first element of the array. As such you can do:
ptr = a;
but not
a = ptr;
Pointers point to an area in memory. Pointers to int point to an area large enough to hold a value of int type.
If you have an array of int and make a pointer point to the array first element
int array[42];
int *p = array;
the pointer still points to a space wide enough for an int.
On the other hand, if you make a different pointer point to the whole array, this new pointer points to a larger area that starts at the same address
int (*q)[42]; // q is a pointer to an array of 42 ints
q = &array;
the address of both p and q is the same, but they point to differently sized areas.

Why do these pointers cause a crash?

I'm a bit confused as to why the following code crashes:
int main(){
int *a;
int *b;
*a = -2;
*b = 5; //This line causes a crash on my system.
return 0;
}
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
Or must you always explicitly allocate memory?
No. You've only declared the pointers, not what they point to. The pointers are allocated on the stack, and since you've not initialized them to anything, their values are garbage.
int main() {
int a = 7;
int *p_a; // p_a contains whatever garbage was on the stack at its
// location when main() is called. (Effectively points nowhere).
p_a = &a; // p_a points to (gets the address of) variable a, also on
// the stack.
printf("Before: a = %d\n", a); // prints 7
*p_a = -2;
printf("After: a = %d\n", a); // prints -2
return 0;
}
I would code up the above example, and step through it in a debugger. You'll see what I mean about what p_a is pointing to.
Shouldn't memory automatically be allocated for two pointers and two integers before run-time because of the declarations?
I only see you specifying two pointers. Where are the two integers?
Or must you always explicitly allocate memory?
Pointers have to point to something. Either local variables on the stack, or malloc'd memory from the heap.
In this code:
int* a;
*a = -2;
a is an uninitialized pointer, dereferencing of which produces undefined behavior, that you were luckily able to observe as a crash of your application.
You need to initialize the pointer (make it point to the valid memory) before you dereference it (i.e. before you use *, the dereference operator):
int a;
int* pA = &a;
*pA = -2;
Consider
int m;
int n;
m = n;
This is invalid because you're trying to use n but you haven't assigned a value to it. Now:
int *a;
*a = -2;
Likewise, this is invalid because you're trying to use a but you haven't assigned a value to it. The value of a is not an int, it's a pointer to int. For example,
int someint;
a = &someint;
*a = -2;
puts -2 into someint. Without the assignment to a, the place to put -2 is undeterminable. Also,
a = malloc(sizeof(int));
*a = -2;
Here, a is given the value of the address of some location in the heap; -2 goes into that heap location.
Perhaps an analogy would be helpful:
Consider the phrase "her dog". This is a reference to someone's' dog, but it won't do to tell me "give her dog a bone" if you haven't told me who she is. Similarly, "pointer to an int" doesn't tell the system which int it is.
Your *a and *b pointers are not initializated properly.
Try this one:
int my_a;
int my_b;
int *a;
int *b;
a = &my_a; // init the pointer a to the direction of my_a int variable
b = &my_b;
*a = 3; // set the my_a value via pointer
*b = 2;
You have just declared pointers but you haven't initialized them. So, you can't be sure that *b = 5 is causing the program to crash. It could be *a = -2 as well. To fix it, you should initialize your pointers as well.
int aval = -2;
int bval = 5;
int *a = &aval; // declared and initialized pointers
int *b = &bval;
// Now you can change the value using the pointer
*a = 15;
*b = 20;

a simple pointer code

#include <stdio.h>
int main(void)
{
int* a;
*a=20;
printf("%i\n",*a);
return 0;
}
I have the code above. when the code in runtime, I always get the error message "filename.exe has stop working". Why?
You did not allocate any memory for the pointer to point at. You can do so like this:
int *a = malloc(sizeof(*a));
or like this:
int value;
int *a = &value;
If you allocate with malloc then you'll want to call free on the pointer when you are finished using it.
Accessing an uninitialized pointer leads to undefined behaviour. In your program it led to segmentation fault, one very common outcome of uninitialized pointer access.
In int* a; a's default value is garbage, and points to an invalid memory, you can't assign to that. And assignment like *a=20; this is causes an undefined behavior at run time. (syntax wise code is correct so compiled) you may some time get a seg-fault too.
either do:
int i;
int *a = &i; // a points to a valid memory that is i
*a = 20;
or with dynamic memory allocation using calloc() or malloc() functions.
int *a = malloc(sizeof(int));
*a = 20;
Remember dynamic allocated memories we have to deallocate (free) explicitly when we have done with that.
You have wild pointer, either assign memory to it using malloc
int* a = malloc(sizeof(int));
or use a stack variable
int b = 0;
int *a = &b;
*a=20;
The problem is in your assignment
*a = 20.
You can't allocate a value to a pointer variable like that.
int b = 20;
a = &b;
Thanks,
Santhosh

Resources