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;
Related
In the following code p is pointer to an int. It is quite clear that p points to the address of i. Through my research i know &p points to the address of pointer p. But i don't get why would you need separate address for that. And also when would you use &p.
int main() {
int i = 3, *p = &i;
printf("%p",&p);
printf("%p",p);
return 0;
}
If p is pointer to int then
int **q = &p;
When you want to use pointer to pointer, then use the address of a single pointer to assign it to pointer to pointer.
Just to make a point that pointer is also a data-type and it stored in the memory location and it holds a valid memory location as its value. The address in which this valid memory location is stored is given by &p
Your printf() also needs to be fixed. %p expects void *
printf("%p",(void *)p);
But i don't get why would you need separate address for that
You don't, but there exists the address of operator so you can take the address of a pointer, which is what
printf("%p\n", &p);
is printing.
And also when would you use &p
There are cases where this might be useful, consider for example that you need to pass a pointer to a function which could be reassigned into the function, you can do something like this
int allocateIntegerArray(int **pointerToPointer, size_t someSize)
{
if (pointerToPointer == NULL)
return 0;
*pointerToPointer = malloc(someSize * sizeof(int));
return (*pointerToPointer != NULL);
}
then you could use this funciton the following way
int *pointer;
if (allocateIntergerArray(&pointer, 10) == 0)
{
fprintf(stderr, "Error, cannot allocate integer array\n");
/* do some extra cleanup or recover from this error, or exit() */
exit(0);
}
The pointers themselves are also variables and as such they need to be sotred somewhere, so the address of a pointer tells you where is the pointer stored, it's value tells you where it is pointing to.
By knowing where it is stored you can do things like the one explained above.
A trivial example:
int nochange(int *c, int *val)
{
c = val; // Changes local pointer c to point to val
// Note that C passes copies of the arguments, not actual references.
}
int do_change(int **c, int *val)
{
*c = val; // Accesses the real pointer c at its real location and makes
// that one point to val
// Even though c is a pointer-to-pointer copy, its value is
// copied too, and the value is the address of the real c
}
int main()
{
int a = 1;
int b = 2;
int *c = &a; // A pointer is also a datatype that resides in memory
printf("%d\n", *c); // Will print 1
nochange(c, &b);
printf("%d\n", *c); // Will print 1
do_change(&c, &b);
printf("%d\n", *c); // Will print 2 because c now points to b
}
I have a similar answer with a bit more detail here about pointer vs pointer-to-pointer: pointer of a pointer in linked list append
I am trying to understand the logic of some code and getting with their use of pointers.
So for example, if two pointers (say A and B) to structures are declared and the equated to each other,
and then the data in a structure is changed through one of the pointers, does it get changed in the second one too or is it just re-written? I guess my question is: will A and B literally point to the same thing or will one point to the copy of the other?
The code does something like this:
somestruct *A;
somestruct *B;
B = A;
A->data = 5;
B->data = 6;
In your example above they will literally point to the same thing.
It is also important to allocate and deallocate memory before and after use however, or else you will get unexpected behaviour and/or segmentation faults.
somestruct *A;
somestruct *B;
A = malloc(sizeof(somestruct));
B = A;
A->data = 5;
B->data = 6;
printf("Data in A: %d", A->data); /* Prints 6 */
printf("Data in B: %d", B->data); /* Also Prints 6 */
...
free(A);
It's also good practice to check the result of malloc and ensure that the operation was successful. This kind of situation can become an issue if for example you want to change the location A points to, and would also like to change the location B points to. Unless you change both, changing one pointers location will not update the other. This is where a double pointer would come in use. EG
somestruct *A;
somestruct **B;
A = malloc(sizeof(somestruct));
B = &A; // Get the address of A
A->member = 5;
printf("Member: %d", (*B)->member); /* Prints 5 */
free(A);
A = malloc(sifeof(somestruct));
A->member = 10;
printf("Member: %d", (*B)->member); /* Prints 10 */
Note that in the double pointer example B does not need updating again.
See the example here: Double Pointer
will A and B literally point to the same thing or will one point to the copy of the other?
A and B will literally point to the same thing
suppose you do something like this
somestruct *A;
somestruct *B;
A = malloc( sizeof(somestruct)) // addded this statement to show that memory allocation is done for A only
B = A;
A->data = 5;
B->data = 6;
this would mean that now pointer B points to the same memory location that A points to, therefore whatever you change (either by using A or B) would change both the pointers data, because essentially its the same data. It is now just being pointed by 2 pointers (namely A and B).
You are changing not the pointers but the object that is referenced to by the pointers. That is it is the object that is been changing using one of the pointers.
For example
#include <stdio.h>
int main()
{
struct A { int i; } a = { 0 };
struct A *p1 = &a;
struct A *p2 = &a;
p1->i = 10;
printf( "%d\n", p2->i );
}
A pointer is not the structure, but simply a memory address (and an instruction to the compiler about the layout of memory), so when you act through the pointer you change the memory. Given another pointer points to the same piece of memory it points to the changed structure.
Of course, if you do something like this:
long *a = malloc(sizeof long);
long *b = a;
and then later:
b = malloc(sizeof long);
then a is not changed, though b is.
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.
I am trying to understand why that code crash:(CodeBlocks C99)
int a;
int **b=0;
*b=&a;
I know that *b is of type int* and &a is also int* so what's the problem here?
Let's take this apart:
int a; /* make a an integer, assuming this is in a function on the stack */
int **b=0; /* make b a pointer to a pointer to an integer, but make it point to 0 */
*b=&a; /* store the address of a at the address pointed to by b, which is 0 */
IE you are explicitly writing the address of a to a zero location. The problem is not type compatibility, it's that you are trying to store something at location zero, which will cause a seg fault.
To fix it do something like:
int a; /* make a an integer, assuming this is in a function on the stack */
int *c = 0; /* make an integer pointer, initialise it to NULL */
int **b=&c; /* make b a pointer to a pointer to an integer, make it point to c */
*b=&a; /* store the address of a at the address pointed to by b, which is c */
b points to a pointer, you point the pointer to 0 / NULL, meaning when you do *b = you are assigning the value to address 0 which will die on most OSs ( on embedded systems this can be valid depending on the processor)
You are dereferencing the NULL-Pointer. b points to NULL and in the next line you are dereferencing it and assigning it a new value.
You are not allowed to write to memory you don't own, and you are especially not allowed to write to NULL.
You cannot set pointers to values like that (*b=&a) because they are at the time not pointing to anything; in order to set their value they must be pointing to something.
int a;
int *tmp;
int **b = &tmp;
*b = &a; //this should work because you are setting a real variable (in this case tmp) to &a
Your int **b=0 is a pointer to int *, that is initialized to NULL, and isn't pointing at an allocated storage area. When you write to *b, you are attempting to dereference a null pointer, which is illegal.
If you were to allocate storage, for example using b=malloc(sizeof(*b)), you would then be able to write into the area pointer at by b using *b=&a, because then *b would be a valid address to write into.
#include <stdlib.h>
int
main()
{
int a;
int **b = (int**)malloc(1 * sizeof(int));
*b = &a;
free(b);
return 0;
}
Your *b = &a has the same effect of b[0] = &a.
I am trying to have a function take some integer pointers passed from my main() function and assign values to them. However, my program crashes when assigning values. Here is my code:
int computeMoveLocation(int* r, int* c, char* board)
{
//some code up here
*r = 0; //This breaks the program
*c = 0;
}
I'm not trying to change the address of the pointer--I'm trying to change the value of the integer being pointed to. However, I am apparently doing something wrong.
Any help would be greatly appreciated.
EDIT:
Here is the relevant code from main(). Please let me know if I should include anything else as well.
int main()
{
//initialization code
//...
while (1)
{
switch (MACHINE_STATE)
{
case COMPUTER_MOVE :
{
//check rows for three Xs
//check columns for three Xs
//check diagonals for three Xs
//otherwise, move anywhere else
int *r, *c;
computeMoveLocation(r, c, board);
computerMove(*r,*c, board);
PREVIOUS_STATE = COMPUTER_MOVE;
MACHINE_STATE = HUMAN_MOVE;
break;
}
//Other cases
}//end switch
}//end while
}//end main
You are passing in pointers but you didn't allocate memory. So they are pointing at a random location in memory.
int computeMoveLocation(int* r, int* c, char* board) {
//some code up here
*r = 0; //This breaks the program
*c = 0;
}
Bad main :
int main() {
int *r;
int *c;
char *board;
// bad, passing in pointers but didn't allocate memory
computeMoveLocation(r, c, board);
return 0;
}
Good main #1:
int main() {
int r = 5;
int c = 5;
char board = 'a';
// fine, passing address of variables on stack
computeMoveLocation(&r, &c, &board);
return 0;
}
Good main #2:
int main() {
int *r = malloc(sizeof(int));
*r = 5;
int *c = malloc(sizeof(int));
*c = 5;
char *board = malloc(sizeof(char));
*board = 'a';
// fine, passing pointers that point to heap
computeMoveLocation(r, c, board);
free(r);
free(c)
free(board);
return 0;
}
int *r, *c;
computeMoveLocation(r, c, board);
computerMove(*r,*c, board);
You define a pointer but don't make it point to anything. Thus, it is a wild or uninitialized pointer; accessing *r as you do in computeMoveLocation will cause undefined behaviour (in your case, a crash).
You have to either initialize the pointer to point at something known, or just pass the address of an existing int:
int r, c;
computeMoveLocation(&r, &c, ...);
or
static int x, y; // static: only one instance of the variable exists
int *r = &x; // initialize pointers
int *c = &y;
computeMoveLocation(r, c, ...);
or
int *r = malloc(sizeof(int));
int *c = malloc(sizeof(int));
computeMoveLocation(r, c, ...);
In that last case, make sure to free the memory afterwards.
You can always pass a pointer and modify the value that the pointer is pointing to. That is how pointers are supposed to be used. But, you should also be careful to see if the pointer does really points to something or not. The pointer should contain a valid address, the value at whose location you can change. If you don't ensure that, then Undefined Behavior will result.
For Example, when you call your computeMoveLocation function, the address which you are passing should either be of stack or of heap. You can see the code below to understand it.
First possibility
int r, c;
char board;
computeMoveLocation(&r,&c, &board);
Second Possibility
int *r, *c;
char *board;
r = malloc(sizeof(int));
c = malloc(sizeof(int));
board = malloc(sizeof(char));
computeMoveLocation(r,c,board);
Please note that char * is also generally used to pass an address to array of charaters, but, in a such a usage, generally it is ensure that it is null terminated or an accompanying length of the array is also passed.
You can anyway get more details on passing aroung pointers by a simple google search.
EDIT
Now, that you have posted your code which calls computeMoveLocation, you see that you should modify your code according to the Second Possibility shown above, since you are declaring r and c as pointers or you should declare them as integers and call as per the First Possibility shown above. But, you are not doing the same which causes the undefined behavior.
Also, in the above examples, I have allocated memory for board, but, in your case, if it originates at some other place and if it has been handled appropriately there, then it need not be malloced.