I got a weird question to do as an exercise :
Write a function which take a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of a pointer of an int as a parameter and assign a value to it.
I think the function I wrote is right (please correct if it's not) but how can I test it ?
void function(int *********anInt)
{
*********anInt = 5;
}
I tried :
int main(void) {
int *********nbr = malloc(sizeof(int));
function(nbr);
printf("%d", *********nbr);
}
But I get a segfault, I just learned about malloc and pointers so I don't fully understand it.
Of course, you can test it, although it looks weird.
#include <stdio.h>
void function(int *********anInt)
{
*********anInt = 5;
}
int main()
{
int n = 0;
int *p1 = &n;
int **p2 = &p1;
int ***p3 = &p2;
int ****p4 = &p3;
int *****p5 = &p4;
int ******p6 = &p5;
int *******p7 = &p6;
int ********p8 = &p7;
function(&p8);
printf("%d\n", n);
return 0;
}
Try
int main() {
int *********nbr;
nbr = malloc(sizeof(int********));
*nbr = malloc(sizeof(int*******));
**nbr = malloc(sizeof(int******));
***nbr = malloc(sizeof(int*****));
****nbr = malloc(sizeof(int****));
*****nbr = malloc(sizeof(int***));
******nbr = malloc(sizeof(int**));
*******nbr = malloc(sizeof(int*));
********nbr = malloc(sizeof(int));
function(nbr);
printf("%d", *********nbr);
}
You'll need a ridiculous main program to go with the assignment from hell!
int main(void)
{
int l0 = 0;
int *l1 = &l0;
int **l2 = &l1;
int ***l3 = &l2;
int ****l4 = &l3;
int *****l5 = &l4;
int ******l6 = &l5;
int *******l7 = &l6;
int ********l8 = &l7;
printf("%d %d %d %d %d %d %d %d %d\n", l0, *l1, **l2, ***l3, ****l4, *****l5,
******l6, *******l7, ********l8);
function(&l8);
printf("%d %d %d %d %d %d %d %d %d\n", l0, *l1, **l2, ***l3, ****l4, *****l5,
******l6, *******l7, ********l8);
return 0;
}
Untested: maybe I didn't count something right, but the general idea is about correct. This is a torture test — for innocent C programmers and for compilers.
An int** is a pointer that points to a pointer:
int myInt;
int* pInt = &myInt;
int** ppInt = &pInt;
An int*** is a pointer that points to a pointer that points to a pointer:
int*** pppInt = &ppInt;
To test your function, you need to carry this on and on, the right number of times.
See md5's solution, however it lacks explaination
Explained:
The reason your test program didn't work is because malloc returns a void* which is simply a memory address (a pointer). You assigned this to an int*****... which means when the program tries to dereference down to the actual int what it's doing is first taking the memory address of the int and dereferencing it (which is okay) but after this since your value (5) is now the value it then derefences that, which should come back with your segfault.
Think of the assignment as nested dereferences:
int ********p8 = *anInt; // p8 == 5
int *******p7 = *p8; // This breaks since dereferencing memory
// address 5 results in a segfault
What was done to avoid this was we actually nested the pointers that way when dereferencing for assignment we have memory addresses (pointers) to dereference to eventually get to the memory address which stores the value.
Related
I am typecasting the address of a character variable whose address 0x7ffc684486ef to an integer pointer. The value at the address 0x7ffc684486ef is 16, when I dereference using the integer pointer it would read 4 bytes starting from address 0x7ffc684486ef, but it return value 0, how is it. Is my understanding wrong ?.
int main()
{
char var;
int *ptr;
ptr = (int *)&var;
printf("%p %p\n", &var, ptr);
*ptr = 16;
printf("%d %d\n", var, *ptr);
return 0;
}
O/P
0x7ffc684486ef 0x7ffc684486ef
16 0
Why the below code does not print anything.
#include <stdio.h>
#define ADDRESS 0x7ffc684486ef
typedef struct Point {
int x;
int y;
}Point;
int main()
{
Point *var = (Point *)(ADDRESS);
var->x = 2;
var->y = 5;
printf("Location: %p\n", var);
printf("Values: %d %d\n", var->x, var->y);
}
O/P:
NIL
C allows wildly unsafe pointer conversion such as ptr = (int *)&var; without protesting. So it's likely that you get the same address even after changing the pointer type.
However, when you de-reference the *ptr = 16; you invoke an impressive number of undefined behavior bugs: out of bounds access, possible misaligned access, strict aliasing violation, accessing memory you don't have access to, and so on. Don't do this, this code is incredibly broken and there's no telling what the result might be. What is undefined behavior and how does it work?
The second example is even worse:
How do you know there is memory you have access to at that address?
It's a misaligned address so you can't access it as a struct on most computers
The access of memory areas unknown by the compiler, such as hardware registers, has to be volatile qualified.
So it would seem that you make a misaligned address somewhere out in la-la-land and this too is wildly undefined behavior. There's no point in reasoning about any behavior you might encounter. Any form of behavior can happen.
Just to clarify the concept related to *p = 16 ...
Look at this piece of code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int numa = -1, num, numb = -1;
int *p = (int *)#
*p = 16;
printf("\n%d %d %d %d", *p, numa, num, numb);
}
When it runs it will output:
16 -1 16 -1
Now try changing the data type to char on the line that declares 'num':
#include <stdio.h>
#include <stdlib.h>
int main()
{
char numa = -1, num, numb = -1;
int *p = (int *)#
*p = 16;
printf("\n%d %d %d %d", *p, numa, num, numb);
}
you will receive "Segmentation fault".
I had to write the following function, which returns two output values.
In order to do so I used a pointer for the second output value of the quotient. However when I wanted to test it with an input it seemed to be crushing. The code is:
#include <stdio.h>
int div( int n, int m, int *quotient)
{
int d = 0;
while (n >= m) {
n = n - m;
d++;
}
*quotient = d;
return n;
}
int main(void)
{
int *p;
int rest;
rest = div(7, 2, p);
printf("n - %i, d - %i", rest, p);
return 0;
}
would be happy to know how to fix it and why it happened at first place
Thanks for your help
Change this:
int *p;
int rest;
rest = div(7, 2, p);
To this:
int p;
int rest;
rest = div(7, 2, &p);
The problem with your code is that p points some random unallocated place (or is a null pointer if you're lucky). The updated version allocates space for the integer and then passes its address to the function. The function then has a pointer to this address and can write the value there. The memory is allocated on the stack (local variable) and so everything is fine.
I get segmentation fault after executing this part of code.If i comment the first printf out,it works fine.Why does this happen?
#include <stdio.h>
int Func (int *a){
printf("%d\n",56 );
printf("a is %d\n",*a );
return 3;
}
int main(){
int N, i, Planet, *a,junk;
junk=scanf("%d", &N );
*a = N;
Planet = Func(a);
printf("%d\n", Planet);
return 0 ;
}
Inside your main function, you defined the int *a pointer variable:
int main(){
int N, i, Planet, *a,junk;
But then you dereferenced the pointer without having previously allocated any memory for it, nor setting it to point to something meaningful:
*a = N;
This results in undefined behavior.
What you probably wanted is to make a point to N?
If so, this is the correct syntax:
a = &N;
Now you can use *a to write some content into N.
P.S.
As a general rule, I'd suggest you to declare one variable per line, and initialize pointers to NULL, e.g.:
int man() {
int *a = NULL;
...
#include <stdio.h>
int main()
{
int* n;
*n = 20; // causes the crash
printf("%d\n", *n);
return 0;
}
but for some reason if i first set int* n = i then I can change the value with *n = 20
there a reason for this?
int i = 19;
int* n;
*n = i;
*n = 20;
edit: thank you everyone for helping i learned a lot from your answers.
int* n;
*n = i;
No, all you see (in both of your examples) is result of undefined behavior. Above you didn't initialize the pointer to point to a meaningful memory - by applying * operator you are dereferencing the pointer and telling it to write some value to the memory it points to, but since you didn't make it point to valid memory - you can't write through that pointer.
This would be fine
int x = 0;
int* n = &x; // Now your pointer points to valid memory
*n = 5; // Value of x will be 5 now
Yes, there is a reason. When you declare :
int* n;
pointer n shows nowhere. So when you try to set its value by
*n = 20;
the program crashes as you are trying to access the contents of a pointer showing nowhere.
On the other hand, when you declare
int i = 19;
int* n;
n = &i;
you make the pointer n show to some valid address. So when afterwards you assign
*n = 20;
you actually access the contents of a valid memory address.
The reason why you can't set the value using that pointer is because its not pointing to a memory address yet, you need to use malloc and give it something to point to.
Hope this helps :D
E.g
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int *n;
n = malloc(sizeof(int));
*n = 20;
printf("n = %d\n", *n);
system("pause");
return 0;
}
#include <stdio.h>
void swap (int *a, int *b)
{
int *tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
}
I'm using codeblocks, and this code won't work, and I don't understand why... On one computer it works perfectly but on the other it won't run at all.
Any help?
Thanks in advance.
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
What you need is a variable tmp to store the value and not a pointer *tmp.
The below code really a poor way of doing this but
int *tmp = malloc(sizeof(int));
*tmp = *a;
*a = *b;
*b = *tmp;
Once done please free the memory using
free(tmp);
Gopi already corrected your code - adding on to the previous answer - i think this is good to know information for a newbie:
Section 4.1 states:
An lvalue (3.10) of a
non-function, non-array type T can be
converted to an rvalue. If T is an
incomplete type, a program that
necessitates this conversion is
ill-formed. If the object to which the
lvalue refers is not an object of type
T and is not an object of a type
derived from T, or if the object is
uninitialized, a program that
necessitates this conversion has
undefined behavior. If T is a
non-class type, the type of the rvalue
is the cv-unqualified version of T.
Otherwise, the type of the rvalue is
T.
When you try to dereference and uninitialized pointer the behavior is undefined. Undefined means anything can happen - there is no guarantee. So you can get different behavior in different environments.
From Wiki Making pointers safer
A pointer which does not have any address assigned to it is called a wild pointer. Any attempt to use such uninitialized pointers can cause unexpected behavior, either because the initial value is not a valid address, or because using it may damage other parts of the program. The result is often a segmentation fault, storage violation or wild branch (if used as a function pointer or branch address).
What you did here:
int *tmp;
*tmp = *a;
is that you created a pointer to int which is not pointing to anything - basically it contains some junk value (could be your pincode even - who knows).
Your mistake was to use uninitialized memory. Always allocate memory to a pointer before using it. Next, don't forget to free the allocated memory after you're done with it.
Also, you should add return 0; at the end of your main() function.
If you don't mind a second opinion, check the below code.
#include <stdio.h>
#include <stdlib.h>
void swap (int *a, int *b)
{
int *tmp = malloc(sizeof(*tmp));
*tmp = *a;
*a = *b;
*b = *tmp;
free(tmp);
}
int main ()
{
int x = 5;
int y = 7;
swap (&x,&y);
printf ("\n x = %d \n y = %d \n",x,y);
return 0;
}
If you want to use pointers, although it does not make any sense at all
void swap(int *a, int *b)
{
int tmp[1];
*tmp = *a;
*a = *b;
*b = *tmp;
}
here tmp is not strictly a pointer, but you can use the * indirection operator on it.
Or
void swap(int *a, int *b)
{
int value = *a;
int *tmp = &value;
*tmp = *a;
*a = *b;
*b = *tmp;
}
Or you can use malloc as Gopi already pointed out.
If you want to use pointers, then do use pointers:
#include <stdio.h>
void swap (int ** ppx, int ** ppy)
{
int * p = *ppx;
*ppx = *ppy;
*ppy = p;
}
int main (void)
{
int x = 5;
int y = 7;
int * px = &x;
int * py = &y;
printf ("\nx = %d\ny = %d\n", *px, *py);
swap (&px, &py);
printf ("\nx = %d\ny = %d\n", *px, *py);
return 0;
}
Result:
x = 5
y = 7
x = 7
y = 5