How does int *p = 10; work? - c

I have a statement int *p = 10; . This statement executes perfectly fine on any compiler. I also know that 10 is put in read-only memory. Is there a way i can access this memory. How can I print this on console? The statement printf("%d",*p) crashes. How can I make it print on console.
Edit
int main()
{
int *p = 10;
}
the above code compiles fine and runs fine.
int main()
{
int *p = 10;
printf("\n%d",*p); //crashes
}
the above code gives segmentation fault. I wanted to know more explanation on this?

By typing int *p = 10; you say to compiler:
Lets have a pointer on integer, called "p".
Set p to 10 => p points on address 10 on memory.
By typing printf("%d",*p); you say to compiler:
Show me -as a integer- what is at the address 10 on memory.
The code
int *p = 10;
Is equivalent to:
int *p;
p = 10;
Is not equivalent to:
int *p;
*p = 10;
Corrected code could be:
// define an integer
int i;
// define a pointer on the integer
int *p = &i;
// set integer to 10, through pointer
*p = 10;
// display integer through pointer
printf("%d",*p);

I think my answer is great for you,you may misunderstand the definition of the pointer and use the pointer in a wrong way. Let`s analyse your code first:
int *p = 10
this statement defines a pointer which is pointed to address 10 in memory, it compiles OK because there's no syntax error--the content of p is the address 10, but you have no idea what's value in address 10, and it generally doesn't have a internal memory to store a value cuz you haven`t allocate the memory for it.it's also very dangerous that you are tring to use a system memory 10.
You can print the address which has been pointed by p:
printf("%d\n", p);//p is pointed to address 10
So when you tried to print the content of p by:
printf("\n%d",*p);
which haven't allocate the memory to store the content,segmentation fault occurs!
If u want to assign value for pointer directly u must dynamic application of memory space for it first, you should write in this way:
int *p = NULL;//the right and safe habit to define a pointer
p = (int *)malloc (sizeof(int));//dynamic application of memory space of pointer p to store value
if (NULL == p)
{
printf("malloc failed!\n");//show error
exit(1);//exit
}
*p = 10;//now you have memory space to store value 10
printf("%d\n", *p);
free(p);//release the memory to avoid memory leaks
p = NULL;//the right and safe habit
You can also write in this way:
int transfer_value = 10;//integer has memory when you declare it
int *p = &transfer_value;//p stores the address of i which content is value 10
printf("%d\n", *p);//because variable i has memory which size is sizeof(int), you can print *p(it stands for the value of i)directly.
Hope my explanation could help you ^_^

Segmentation fault is a error when there is a memory access violation. Dynamic memory allocation will solve your problem. Kernel will decide which memory address should be used to store the value.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p = malloc(sizeof(int)); //Kernel will assign a memory from Heap segment
*p=10;
printf("\n%d",*p);
free(p);
}

You have created a pointer, not a value. You probable want just int i=10. Otherwise, the program is accessing random memory at address 10 and will crash.

When you assign the value 10 to your pointer, you actually assign the address 10 to it. When you initialize you don't get any error, but when you try to print it you have to access it, and you don't have access to this memory address (that's why you have a segmentation fault).
If you do this :
int i = 10;
int *ptr = &i;
printf("%d\n", *ptr);
It will work because you make the pointer points to the variable i which contains the value 10.

int *p = 10;
creates a pointer p and sets it to point to the memory address 10, which is most likely not an accessible address on your platform, hence the crash in the printf statement.
A valid pointer is obtained by using the unary & operator on another object, such as
int i = 10;
int *p = &i;
or by calling a function that returns a pointer value such as malloc or fopen. Some platforms may expose specific addresses for particular operations, but those are usually well-documented and not such low address values.

Related

pointer reassignment gives segmentation fault

I'm having an issue understanding why I can't make the re-assignment for lastPrefix, on the line specified it gives me a segment fault. I appear to be missing something fundamental.
char * somefunc(char ** strs, int numStrings)
{
char * lastPrefix;
printf("%d\n", *(strs[0]+0));
printf("%d\n", *(strs[1]+0));
printf("%d\n", *(strs[2]+0));
printf("%d\n", *(strs[0]+1));
printf("%d\n", *(strs[1]+1));
printf("%d\n", *(strs[2]+1));
printf("%d\n", *(strs[0]+2));
printf("%d\n", *(strs[1]+2));
printf("%d\n", *(strs[2]+2));
printf("%d\n", *(strs[0]+0));
printf("%d\n", *(strs[1]+0));
printf("%d\n", *(strs[2]+0)); // ALL IS WELL
*lastPrefix = *(strs[1]+0);
*lastPrefix = *(strs[2]+0);
*lastPrefix = *(strs[0]+1); // WILL SEGMENT FAULT HERE
*lastPrefix = *(strs[1]+1);
*lastPrefix = *(strs[2]+1);
}
int main()
{
char * strs[] = {
"flower", "flow", "flight"
};
char * res = somefunc(strs, SIZEOF(strs));
}
Could I also ask for a good reference for C pointers?
When you create any variable, whether it's pointer or data, the initial value of the variable will be some garbage or 0. In your case,
char *lastPrefix;
Is such a variable, which contains some garbage value. You have to give it a valid value using malloc() or something like that. Or else, when you de reference it(*), it might points to some inaccessible or even nonexistent memory location. Maybe it points to the middle of your code. Maybe it points to NULL. Memories like that is inaccessible in userspace. So, windows(or linux) kills your program.
What you want to do:
char *lastPrefix;
lastPrefix=malloc(101); //holds strings upto 100 characters
The malloc() will allocate value into your variable from heap and the program should work okay.
Just remember to free the memory at the end: free(lastPrefix);
int *ptr; // pointer variable declaration */
int kk; // actual variable declaration */
*a = 11; // `a` pointing to unknown memory address and accessing this will give segmentation fault/
a = &kk; *a = 11 // This is valid. store address of `kk` in pointer variable */
Similarily, in your code lastPrefix points to an unknown address, accessing it will give you segmentation fault.

I'm new to C but I'm getting "Segmentation Faults" (Seg fault/SIGSEGV). Why? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
When I try to run the following logic snippits, I get segmentation faults, why? Sometimes I don't get segmentation faults but instead I get odd output that does not make sense...
1. Changing a string's character
char *str = "Hello!";
str[0] = 'h'; // SIGSEGV
2. Modifying the value of a pointer
int *num_ptr;
*num_ptr = 6; // SIGSEGV
3. Using an array or pointer returned from a function
int *getPoint()
{
int cords[2] = {10, 20};
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1]; // SIGSEGV (or sometimes total = 0?)
4. Looping through n-sized array in function
void print_loop(int *array)
{
for(int i = 0; i < sizeof(array); i++)
printf("array[%d] = %d\n", i, array[i]); // SIGSEGV
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums);
What do I do to fix each of these and understand why they happen?
char *str;
int *num_ptr;
int *point;
^^ this code just creates a variable for you to then use which is a pointer to memory. Realize it never allocates or reserves memory.
so for 2 where you do *num_ptr = 6; you are trying to put the value of 6 into memory pointed to by num_ptr. But num_ptr does not point anywhere yet, it either points to NULL or is uninitialized and contains some random number value. If it contains some random number value odds are it is not valid memory location, hence the segmentation violation. And if it were NOT to result in a SIGSEV and the code ran then it would be by chance you got lucky; you would never want to program this way having basic concepts of programming happen by chance.
Same principle applies for all your other examples. It doesn't matter the data type. It's the basic problem of having a pointer to memory, and whether or not you have (by whatever means) reserved or allocated some valid range of storage space (RAM, disk, wherever).
str[0] = 'h'; is the same thing as *str = 'h';
str[1] = 'h'; would be the equivalent of *(str+1) = 'h';
str[2] is *(str+2)
and so on,
where str is a pointer to the starting location of a range of memory,
then because str is of data type CHAR, +1 moves 1 byte, +2 moves 2 byte.
If it were of type INT where int is 4 bytes, then +1 would be the
initial memory location + 4.
Using an array or pointer returned from a function
This doesnt't work, because you create a pointer and reserve a memory area inside a function, without malloc. When this function ends, you lose this reserved area.
So, you can't make a function that returns a pointer this way. Read a little about malloc() function.
Looping through n-sized array in function
This isn't the right way to loop through a n-sized array, sizeof return the number of bytes that you need tho allocate that structure, not how many elements you have in the array. A suggestion is by as a parameter how many elements you have, if it is a string, you can use strlen, from string.h.
these are common pit falls when someone tries migrate to C from a virtual language such as Java, C#, Python, or JavaScript. The problem is that they do not understand the concept of memory management because virtual languages take care of that now. Hopefully new programmers wanting to learn C can be directed to this answer and avoid these pitfalls -- and ultimately prevent these types of questions from filling the front page of c every day. I am going to be short worded as possible, as I know that 90% of you have already looked at this paragraph and said "lol tl;dr".
What is a Segmentation Fault (seg fault)
It's when you try to access memory that's not yours. Or you try to write to memory that is read only -- The operating system is the one responsible for enforcing this.
An analogy: address in memory are like house address on the streets. And the things inside the houses would be the data itself. If you own a house, you go to its address and add and remove furniture as you please. If you don't own the house, you're simply breaking an entry and the police (The OS) arrest you (seg fault).
Common ways to get it
P1. Changing a string's character
char *str = "Hello!";
str[0] = 'h'; // SIGSEGV
Problem: a string literal (declared within quotes, "LIKE SO") may not be modified. Attempting to do so causes undefined behavior.
Solution: allocate your string in an array.
char str[] = "Hello!";
str[0] = 'h';
P2. Modifying the value of a pointer
int *num_ptr;
*num_ptr = 6; // SIGSEGV
Problem: num is pointer, but its address has not been defined. You can't derreference a pointer unless you give it a valid address.
Solution: Make sure you point your pointers®.
int *num_ptr;
int num;
num_ptr = &num; // num_ptr equals the address of num
*num_ptr = 6;
P3. Using an array or pointer returned from a function
int *getPoint()
{
int cords[2] = {10, 20};
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1]; // SIGSEGV (or sometimes total = 0?)
Problem: cords is an array with automatic storage inside the function getPoint(). When this function returns, the array no longer exists, which means that point now points to invalid memory.
Solution #1: allocate coords with dynamic memory using, for example, malloc(). Dynamic memory exists as long as your program is running, or until you release it with free().
int *getPoint()
{
int *cords = malloc(2 * sizeof(int)); // get 2 ints on permanent (heap) memory
cords[0] = 10;
cords[1] = 20;
return cords;
}
/* ... */
int *point = getPoint();
int total = point[0] + point[1];
free(point); // manual destroy
Solution #2: declare the array outside the function and pass its address to getPoint(). Now instead of returning the array, it receives and modifies it.
int *getPoint(int *cords)
{
cords[0] = 10;
cords[1] = 20;
return cords;
}
/* ... */
int cords[2];
int *point = getPoint(chords);
int total = point[0] + point[1]
P4. Looping through n-sized array in function
void print_loop(int *array)
{
for(int i = 0; i < sizeof(array); i++)
printf("array[%d] = %d\n", i, array[i]); // SIGSEGV
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums);
Problem: In C, there is nothing holding your hand. This means you have to keep track of your own damn array lengths.
Solution: Whenever you pass an array into a function, you MUST also pass the size of the array.
void print_loop(int *array, int array_len)
{
for(int i = 0; i < array_len; i++)
printf("array[%d] = %d\n", i, array[i]);
}
/* ... */
int nums[3] = {1, 2, 3};
print_loop(nums, 3);
"My program does not have a seg fault and/or but it gives a strange result"
Seg faults and things that should cause seg faults are known as "undefined behavior". This means that the error will be different based on what compiler is used, what OS, what CPU, ect. Some cases there will not be an error at all, however that does not mean its OK. It's like saying "If OJ can get away with it then so can I" and then being surprised by the results.

Segmentation fault (core dumped) in c program

i am using gcc compiler on ubuntu 14.04 LTS for compilation of following c program
#include<stdio.h>
void main()
{
int *a,*b;
*a=2;
*b=3;
printf("\n printing address.....\n address of a = %d \n address of b = %d \n",a,b);
printf("\n\n printing values ..... \n value of a = %d \n value of b = %d \n",*a,*b);
}
and when i run above program than i get following in output
output: Segmentation fault (core dumped)
please suggest where i am doing wrong.
thanks
You're declaring and using pointers (pointed-to memory), without allocating space for them.
Just declaring:
int *a;
doesn't give you memory to use, this just declares a variable that can reference memory.
The pointer, once declared, is un-initialized, and will point to some part of memory that doesn't belong to you. Using that memory - in your case, putting a value there - will result in undefined behavior; you see a core dump when you touch that memory.
In order to get some space to use, learn about malloc:
int *a = NULL; // good practive to initialize/reset pointers to NULL
// malloc will give you space for 1 int, and a will point to that new space
a = malloc(sizeof(int));
if (a != NULL) // malloc returns NULL in the event of a failure
{
// a is non-NULL so now we can use the memory pointed-to:
*a = 5;
// other code that uses a goes here:
...
// and when you're finished with a give the memory back:
free(a);
a = NULL;
}
When you declare a pointer
int* p;
it is similar as declaring an integer variable:
int v;
the contents of v is uninitialized - same with p - it is also uninitialized so when you use p e.g. *p you may be dereferencing an address anywhere in memory, even in read-only memory. Instead you need to initialize the variables.
int v = 0;
int* p = &v; // p points to v in memory

Relation between pointers and the memory in the heap

I am a new C developer. I have been programming in Java for 3 years now.
I noticed the manual memory allocation I have to do in C.
However, it is still ambiguous to me when it comes to pointers and memory allocation.
I will say what I understand and please if anyone has any comment on what I have to say, please correct me.
So let's say I have:
int *a;
So what this does is creates a pointer called a that points to an integer value.
int *a = address;
If I print address, I will get the address.
Let's say I want the value, I do what we call dereferencing and
int *a = *value;
If I print value in this case, I would get the actual number stored in memory.
I noticed in the ebook I am using, that sometimes, we allocate memory in the heap.
Is it always the case? Everytime I need to use a pointer for a string for example using char*, I have to use alloc() and sizeof() to respectively allocate memory according to the size of the intended type?
OK. Pointers for the Java guy.
When you declare
int *a;
it is the same as in Java doing:
Integer a;
Java does not have pointers, but all objects are held by references. So,
Integer a = new Integer(3);
is the same as:
int *a = malloc(sizeof(int));
in C.
Now, Java does not have an & operator, and you cannot do pointer arithmetic, but references really are roughly the same otherwise.
To answer your questions:
does it always have to come from the heap?
No. In C you can point a pointer at something that is already allocated on the stack (or anywhere else in RAM, such as a DMA register for doing hardware interactions):
void f() {
int i;
int *a = &i;
*a = 3; // same as i = 3
a = (int*)0x12340000; // some address in memory, possibly screen RAM?
*a = 0xffffffff; // possibly set some colors on the screen
}
Do I have to use malloc and sizeof every time to allocate space?
If you do use malloc, then yes, you have to specify how much space you want. But you can just as easily ask the compiler to allocate the space in static data space:
void f() {
char *p = "hello";
....
}
In this case, the literal string typically becomes part of the compiled program, and is placed in a statically allocated spot at program startup by the OS.
int *a = *value;
This is incorrect unless value is declared to be an int **:
int **value;
Below is a sequence of using an int pointer with appropriate comments:
int num1; // Declare an int
int num2; // Declare a different int
int *pNum = &num1; // Declare an int pointer and set its value to the address of num1
*pNum = 6; // Set the value of num1
pNum = &num2; // Change value of int pointer to the address of num2
*pNum = 10; // Set the value of num2

Directly assigning values to C Pointers

I've just started learning C and I've been running some simple programs using MinGW for Windows to understand how pointers work. I tried the following:
#include <stdio.h>
int main(){
int *ptr;
*ptr = 20;
printf("%d", *ptr);
return 0;
}
which compiled properly but when I run the executable it doesn't work - the value isn't printed to the command line, instead I get an error message that says the .exe file has stopped working.
However when I tried storing the value in an int variable and assign *ptr to the memory address of that variable as shown below:
#include <stdio.h>
int main(){
int *ptr;
int q = 50;
ptr = &q;
printf("%d", *ptr);
return 0;
}
it works fine.
My question is, why am I unable to directly set a literal value to the pointer? I've looked at tutorials online for pointers and most of them do it the same way as the second example.
Any help is appreciated.
The problem is that you're not initializing the pointer. You've created a pointer to "anywhere you want"—which could be the address of some other variable, or the middle of your code, or some memory that isn't mapped at all.
You need to create an int variable somewhere in memory for the int * variable to point at.
Your second example does this, but it does other things that aren't relevant here. Here's the simplest thing you need to do:
int main(){
int variable;
int *ptr = &variable;
*ptr = 20;
printf("%d", *ptr);
return 0;
}
Here, the int variable isn't initialized—but that's fine, because you're just going to replace whatever value was there with 20. The key is that the pointer is initialized to point to the variable. In fact, you could just allocate some raw memory to point to, if you want:
int main(){
void *memory = malloc(sizeof(int));
int *ptr = (int *)memory;
*ptr = 20;
printf("%d", *ptr);
free(memory);
return 0;
}
First Program with comments
#include <stdio.h>
int main(){
int *ptr; //Create a pointer that points to random memory address
*ptr = 20; //Dereference that pointer,
// and assign a value to random memory address.
//Depending on external (not inside your program) state
// this will either crash or SILENTLY CORRUPT another
// data structure in your program.
printf("%d", *ptr); //Print contents of same random memory address
// May or may not crash, depending on who owns this address
return 0;
}
Second Program with comments
#include <stdio.h>
int main(){
int *ptr; //Create pointer to random memory address
int q = 50; //Create local variable with contents int 50
ptr = &q; //Update address targeted by above created pointer to point
// to local variable your program properly created
printf("%d", *ptr); //Happily print the contents of said local variable (q)
return 0;
}
The key is you cannot use a pointer until you know it is assigned to an address that you yourself have managed, either by pointing it at another variable you created or to the result of a malloc call.
Using it before is creating code that depends on uninitialized memory which will at best crash but at worst work sometimes, because the random memory address happens to be inside the memory space your program already owns. God help you if it overwrites a data structure you are using elsewhere in your program.
In the first example, ptr has not been initialized, so it points to an unspecified memory location. When you assign something to this unspecified location, your program blows up.
In the second example, the address is set when you say ptr = &q, so you're OK.
You can set a value for the pointer, but once you've asked for memory for it using "new". This is how your code should look
int main(){
int *ptr;
ptr = new int; //ask for memory
*ptr = 20;
printf("%d", *ptr);
return 0;
}

Resources