segmentation fault in this pointers program in C - c

I keep getting a segmentation fault (core dumped) message whenever I try to run this C program.
#include <stdio.h>
int main()
{
int i = 200, *p, *q, *r;
p,r = &i;
q = p;
*q = *p + 1;
printf("*p = %d\n", *p);
printf("*r = %d\n", *r);
return 0;
}
It didn't have any rs at first but I had to add rs as an alias to i and then Add print statements to output the dereferenced values of q and r.

In your code
p,r = &i;
does not assign p, it leaves p uninitialized. Next, the very moment you dereference p (and q also, as it was assigned with the value of p) you hit
undefined behavior, as you're dereferencing invalid memory.
You need to use
p = r = &i;
Compile your code with proper warnings enabled and, with your code, you should see something similar to
warning: left-hand operand of comma expression has no effect [-Wunused-value]
p,r = &i;
^

Use this:
p = &i;
r = &i;
instead of
p,r = &i;
Uninitialized pointer is bad.

//I write that as an answer because i still don't have 50 reputation
1: I didn't understand what do you want that the program will do. the use of q and r is useless.
2: p,r=&i; is not a good command. use p=r=&i or p=&i; r=&i; or
p=&i; r=p;

i have made the correction in your code and it is working fine please have look into it.
`#include <stdio.h>
int main()
{
int i = 200, *p, *q, *r;
p = &i;
r = &i;
q = p;
*q = *p + 1;
printf("*p = %d\n", *p);
printf("*r = %d\n", *r);
return 0;
}`

Related

add local variable and pointer variable

I'm a beginner in C language.
I'm practicing several codes on my own, while doing I came across this algo.
Below is the code.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int *p;
printf("value of p = %d\n", p);
p = 2;
printf("value of p = %d\n", p);
a = a+p;
printf("value of addition =%d\n", a);
return 0;
}
**OUTPUT**
value of a = 1
address of a = 947268620
value of p = 947268880
value of p = 2
value of addition =6
Why I'm getting 6 instead of 3,
is there anything I'm missing on result
because you're not setting the value of the address p is pointing to to 2, you're assigning/pointing the variable int *p to the value 2 in memory, which is not memory you should be accessing. Instead, you need to point p to memory you have access to (a variable or dynamically allocated memory) and dereference the pointer using *p = 2 which accesses the value that p is pointing to. Your code should instead look like this
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a);
int _p = 0;
int *p = &_p;
printf("value of p = %d\n", *p);
*p = 2;
printf("value of p = %d\n", *p);
a = a+*p;
printf("value of addition =%d\n", a);
One has to "walk right past" the compiler warnings about that code.
Below is the same code with coercive casting to silence some of the warnings. An additional calculation and print statement should make obvious how the compiler deals differently with the values of pointers (memory addresses) and the values of integers.
#include <stdio.h>
int main() {
int a = 1;
printf("value of a = %d\n", a);
printf("address of a = %u\n", &a); // incorrect format spec for printing address
int *p;
printf("value of p = %d\n", p); // uninitialised and undefined behaviour
p = (int*)2; // coercive casting integer to pointer-to-integer
printf("value of p = %d\n", p); // incorrect format spec for a memory address
a = (int)(a + p); // coercive casting address to integer
printf("value of addition =%d\n", a);
// ADDED these statements
a = 1; // restore value of a
a = a + (int)p; // coercive casting address to integer
printf("value of addition =%d\n", a);
return 0;
}
value of a = 1
address of a = 1703728
value of p = 1
value of p = 2
value of addition =6
value of addition =3 <== was this the expected result?
C will try to do its best with explicit program statements.
"Garbage in, garbage out."
Write correct code, not 'cute' code.
Thanks for your response Awayy. Helpful.
I got the output I needed. But the thing I need to know is, in what logic
the line a = a+p; gave 6 as result in my code.
As u said I'm assigning 2 as address to p(which is p = 0x2).
So, when the addition happens a = 1 and p = 0x2 which has a random value that we don't know that is because I'm not assigning a particular address to the pointer variable p. It results 6 I'm I right.

Why is it pointing to the same address?

#include<stdio.h>
int main() {
int x = 5;
int* p = &x;
*p = 6;
int** q = &p;
int *** r= &q;
printf("%d\n",*p); //dereferencing p
printf("%d\n",*q); //getting address of q
printf("%d\n",**q); //dereferencing q
printf("%d\n",**r); //getting address of r
printf("%d\n",***r); //dereferencing r
}
Variable q has the memory address of p while variable r has the memory address of q, then why does when trying to print the memory address of q and r same results are getting produced?
Your comments show that you have misunderstood a few things here.
printf("%d\n",*q); //getting address of q
You're NOT getting the address of q. You're dereferencing q, which happens to be the address of p. The * IS the dereferencing operator. If you want to print the address of q, then do this:
printf("%p\n", (void*)&q); // No asterisk and you should use the %p specifier for printing pointers.
So, because you have made the assignment p=&x; q=&p; then
**q is the same as x or *p
*q is the same as p
q is the the same as &p
&q is the address of q

Pointer to pointer as argument in a function

I have the following code:
void change_adrs(int **q)
{
int * otheraddess;
*q = otheraddress;
}
I can't understand this assignment: *q = otheraddress;
Could anybody help me to explain this. Why can't we use another assignment, such as:
**q = otheraddress;
*q = *otheraddress;
q = &otheraddress;
void change_ptr(int **q)
{
*q = malloc(somemem);
}
void foo()
{
int *ptr;
change_ptr(&ptr);
}
in this example it will change the value of the ptr itself. When you pass a single star pointer you can only change the referenced object.
Look at the assignment of *q = otheraddress; the same as you look at the following:
int x = 4;
int y = x;
you take 2 vairables of the same type and make an assignment between both of them.
In your case, you use the address of int vairables.
int *otheraddress; is a vairable who can get an address (& operator) to int vairable such as:
int x = 4;
int *p = &x; //p<=the address of x
and int **q; can get an address of a vairable which can get int address. such as you 3rd assignment (which should work fine):
int x = 4;
int *p = &x;//p<=the address of x
int **q = &p;//q<=the address of p
for the other assignmets:
**q = otheraddress; you try to assign int* into int**
*q = *otheraddress; you try to assign int into int *
After declaring the variables, * dereferences them.
For example after declaring something like int **a;, when using it we have:
**a value in value in location stored in a(which is ultimately an int)
*a value in location stored in a (which is another location)
a location stored in a
&a location of a itself
Lets take a look and see why each of your examples don't work:
**q = otheraddress; assigning a location to an int ×
*q = *otheraddress; assigning an int to a location ×
Edit: Lets take a look at these two examples:
q = &otheraddress; assigning a location to a location ✓
*q = otheraddress; assigning a location to a location ✓
Lets look at it this way:
Suppose we have:
int *a;
int **q;
in order to prevent segmentation faults in the future, lets first assign some address to a:
int t = 5
a = &t;
Lets look at the addresses afterq = &a:
//first snippet
0x7fffc3a2b338 // &a
0x5596853c98c0 // a
5 // *a
0x7fffc3a2b340 // &q
0x7fffc3a2b338 // q
0x5596853c98c0 // *q
5 // **q
As expected, &a is put into q, and a holds &t, so **(&a) and **(q) will both hold a value of 5.
Now lets look at the addresses after*q = a:
//second snippet
0x7fffc3a2b338 // &a
0x5596853c98c0 // a
5 // *a
0x7fffc3a2b340 // &q
0x7fffc3a2b345 // q
0x5596853c98c0 // *q
5 // **q
Here, a is put into *q, and a itself is &t, so *(a) and *(*q) with both hold a value of 5.
To understand the difference, we look at an example:
int b = 3;
a = &b;
Using this after the first snippet, a is given another address, and q was declared &a(which hasn't changed), therefore **(q) has the same value as **(&a), which is now 3.
This is just like saying:
int a = 3;
int *b = &a;
a = 5; //even though a has changed, b retains its old value of &a, thus *(b) == *(&a) == 5
However on the second snippet, *q was already declared as a before it had changed, so even though a now has a new address, the address inside *q still hasn't changed. Thus trying to access *(*q) will use the old address and give us 5 again.
This is just like saying:
int a = 3;
int b = a;
a = 5; //even though a has changed, b still retains it's old value of 3

Why is the output of the following program 2 97 and not 2 2?

In the following code why doesn't the address of j gets overwritten in p when we call the foo function?
#include <stdio.h>
int main()
{
int i = 97, *p = &i;
foo(&i);
printf("%d ", *p);
}
void foo(int *p)
{
int j = 2;
p = &j;
printf("%d ", *p);
}
You are printing with foo - which sets p to 2, then you call a print to p, which is still set to 97 in that scope. foo does not set p globally.
Because p in main is another variable than p in the function. Consequently, even if p is changed inside the function, the value of p in main is still the same and still points to 97.
In more details:
int main()
{
int i = 97, *p = &i; // i is 97 and p points to i
foo(&i);
printf("%d ", *p); // This prints what p points to, i.e. 97
}
void foo(int *p)
{
int j = 2; // Here p still points to i in main
p = &j; // Now p points to j, i.e. the value 2
printf("%d ", *p); // So this prints 2
}
Just to repeat: The important thing is that p in main and p in foo are two different variables.
If you want the program to print 2 2 you can change the function to:
void foo(int *p)
{
int j = 2;
*p = j; // Change this line. This will change i in main
// and thereby also the value that p in main points to
printf("%d ", *p);
}
Below are the steps:
int main()
{
int i = 97;
int* p = &i; // 1. p points to i, i is 97.
foo(&i); // 2. Pass the address of i by value.
printf("%d ", *p); // 6. Print the value of i as neither p nor i have not changed inside foo().
}
// I've renamed the parameter name from p to q for clarity. q is local to
// foo() only; changes made to q are only visible within foo().
void foo(int* q)
{ // 3. q contains a copy of i's address.
int j = 2;
q = &j; // 4. q is set to the address of j.
printf("%d ", *q); // 5. Print the value of j.
}
If you would have done *q = 2 inside foo() you would have changed i's value to 2. That's because q contains the address of i.
The p in main is a different object in memory than the p in foo. Writing to one has no effect on the other. If you want foo to update the value of p in main, then you must pass a pointer to p:
#include <stdio.h>
int main()
{
int i = 97, *p = &i;
foo(&p);
printf("%d ", *p);
}
void foo(int **p)
{
int j = 2;
*p = &j;
printf("%d ", **p);
}
WARNING - doing this will invoke undefined behavior, since p will point to an object that no longer exists - once foo exits, j no longer exists, and p will be an invalid pointer. You may get the output you expect, or you may not.
In order for a function to write to a parameter, you must pass a pointer to that parameter:
void foo( T *ptr )
{
*ptr = new_value(); // updates the thing ptr points to
}
void bar( void )
{
T var; // var is an instance of T
foo( &var ); // have foo update the value of var
}
This is true for any non-array type T, including pointer types. If we replace T with the pointer type P *, we get
void foo( P * *ptr )
{
*ptr = new_value(); // updates the thing ptr points to
}
void bar( void )
{
P * var; // var is an instance of P *
foo( &var ); // have foo update the value of var
}
The semantics are exactly the same - the only thing that's changed is that var starts out as a pointer type.
Things get weird with array types, which we're not going to go into quite yet.

C function with pointers work on one computer, and doesn't work on another

#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

Resources