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
Related
My Doubt is regarding only memory allocation so don't think about program output
#include<stdio.h>
int main(){
for(int i=0;i<20;i++){
char *str=malloc(sizeof(char)*6); //assuming length of each string is 6
scanf("%s",str);
insertinlinkedlist(str);
}
}
whenever i allocate memory here as shown above only the base address of char array will pass to linked list,and that is the memory block allocated for char array is inside main only and i am storing the base address of that array in str which is local to main and is passed to insetinlinkedlist
I want to ask whenever memory is allocated inside loop than why the number of
memory blocks(no of char arrays declared ) are created equal to n (number of time loop runs) since variable name is same we should be directed to same memory location
Note I have checked in compiler by running the loop all the times when loop runs memory the value of str is different
is The above method is correct of allocating memory through loop and through same variable "Is the method ensures that every time we allocate memory in above manner their will be no conflicts while memory allocation and every time we will get the address of unique memory block"
Now above doubt also creates a doubt in my mind
That if we do something like that
int main(){
for(int i=0;i<n;i++){
array[50];
}
}
then it will also create 50 array inside stack frame
malloc returns a pointer to the first allocated byte. Internally it keeps track of how much memory was allocated so it knows how much to free (you do need to insert calls to free() or you'll leak memory, by the way). Usually, it does this by allocating a little bit of memory before the pointer it gives you and storing the length there, however it isn't required to do it that way.
The memory allocated by malloc is not tied to main in any way. Currently main is the only function whose local variables have a pointer to that memory, but you could pass the pointer to another function, and that function would also be able to access the memory. Additionally, when the function that called malloc returns, that memory will remain allocated unless manually freed.
The variable name doesn't matter. A pointer is (to first approximation) just a number. Much like how running int a = 42; a = 20; is permitted and replaces the previous value of a with a new one, int *p = malloc(n); p = malloc(n); will first assign the pointer returned by the first malloc call to p, then will replace it with the return value of the second call. You can also have multiple pointers that point to the same address:
int *a = malloc(42);
int *b = malloc(42);
int *c = a;
a = malloc(42);
At the end of that code, c will be set to the value returned by the first malloc call, and a will have the value returned by the last malloc call. Just like if you'd done:
//assume here that f() returns a different value each time
//it's called, like malloc does
int a = f();
int b = f();
int c = a;
a = f();
As for the second part of your question:
for(int i=0;i<n;i++){
int array[50];
}
The above code will create an array with enough space for 50 ints inside the current stack frame. It will be local to the block within the for loop, and won't persist between iterations, so it won't create n separate copies of the array. Since arrays declared this way are part of the local stack frame, you don't need to manually free them; they will cease to exist when you exit that block. But you could pass a pointer to that array to another function, and it would be valid as long as you haven't exited the block. So the following code...
int sum(int *arr, size_t n) {
int count = 0;
for (size_t i = 0; i < n; i++) {
count += arr[i];
}
return count;
}
for(int i=0;i<n;i++){
int array[50];
printf("%d\n", sum(array, 50));
}
...would be legal (from a memory-management perspective, anyway; you never initialize the array, so the result of the sum call is not defined).
As a minor side note, sizeof(char) is defined to be 1. You can just say malloc(6) in this case. sizeof is necessary when allocating an array of a larger type.
A "Deeltal" keeps track of how many dividers an integer has (count) and keeps them in an array (dividers).
Examples:
value = 8 -> count = 3 and dividers = {1,2,4}
value = 10, count = 3, dividers = {1,2,5}
Hope everything is clear, take a look at the following code:
typedef struct{
int value;
int count;
int* dividers;
} Deeltal;
void free_dividers(Deeltal *g){ /*Deletes the int* dividers of a given Deeltal*/
free (g - > dividers);
}
/* the following two functions have the same purpose: deleting the content of a
given amount of "Deeltal" AND deleting the pointer to it aswell*/
void free_amountOfdeeltal(Deeltal *d, int amount){
int i;
for (i = 0; i < amount; i++){
free_dividers(&d[i]);
}
free(d);
}
void free_amountOfdeeltalVersion2(Deeltal **g, int amount){
int i;
for(i = 0; i < amount; i++){
free_dividers(&(*g)[i]);
}
free(*g);
}
If my main looked something like this
int main(void){
/*EDIT 3/11/2017: forgot to allocate memory for *d and initializing g.
Thanks for pointing this out*/
Deeltal g = 0;
g.value = 6; g.count = 3; g.dividers = {1,2,3};
Deeltal *d = malloc(sizeof(Deeltal));
d->value = 6; d->count = 3; d->dividers = {1,2,3};
free_amountOfdeeltal(&g);
free_amountOfdeeltalVersion2(&d);
}
What is the difference between free_amountOfdeeltal and free_amountOfdeeltalVersion2?
Both should do the same thing: releasing the memory of a Deeltal and also deleting the pointer pointing to that memory.
On a sidenote:
How do you delete the memory as well as the pointer?
Not withstanding calling this function with invalid data as pointed out by others .. I'll attempt to answer the question I think you are asking.
On a sidenote: How do you delete the memory as well as the pointer?
You can't really "delete the pointer" in this context as a pointer is simply a variable that is assigned an address. You delete memory that was allocated to you by passing free a pointer to the memory. Note that free does not modify the value of the pointer at all. (It can't because the pointer is passed by value.) After the call to free the pointer still points to the same memory address.
If what you mean is "how can I assign a meaningful value to the pointer to identify that its memory has already been deleted," then you can use the second form of your function:
void free_amountOfdeeltalVersion2(Deeltal **g, int amount);
and set *g to NULL before returning. You can then use this information than the pointer is NULL to identify the memory has already been deleted.
You didn't allocate any memory for d so your pointer doesn't point to any structure. Therefor, you can't access its properties or free its memory because you didn't reserve it in the first place. There's no way this code could come remotely close to compiling.
First of all you should be allocating memory for a "Deeltal" structure like this:
Deeltal *d = malloc(sizeof(Deeltal));
I recommend you go back and relearn how pointers work, as you're doing some really weird stuff there.
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.
The pointer to my global variable is turning to crud after freeing the local resource that I use to set the value in c.
this is the .c class
char* resource_directory;
void getResourcePath()
{
char *basePath = SDL_GetBasePath();
char* resource_dir = (char*)malloc(37 * sizeof(char));
for(int i = 0; i < 25; i++)
{
resource_dir[i] = basePath[i];
}
strcat(resource_dir, "resources/");
resource_dir[36] = '\0';
*resource_directory = *resource_dir;
free(basePath);
// free(resource_dir); <--- If I free here the value goes to crud
}
(this line below should say the value at resresource_directorydir equals the value at resource_dir) right?
*resource_directory = *resource_dir;
so the value at the address of the first pointer should get the value of the address at the 2nd but after trying to free the resource towards the end of the function.
even doing a print statement of the addresses show that they have different addresses.
SDL_Log("%d, %d", &resource_directory, &resource_dir);
example output : 245387384, 1361037488
I get the feeling that I am making a silly mistake here but I don't know what it is.
This line,
*resource_directory = *resource_dir;
is assigning the first value resource_dir points to, to the uninitialized pointer resource_directory, it's equivalent to
resource_directory[0] = resource_dir[0];
which is clearly not what you want.
You need to assign the pointer
resource_directory = resource_dir;
but you shouldn't use a global variable for that, and specially
Don't malloc() it, you have to free() everything you malloc() and global variables make it hard.
Don't use malloc() for fixed size objects, instead declare it as an array with the appropriate size, like this
char resource_directory[37];
Copy strings with strcpy() instead of writing a loop your self
for(int i = 0; i < 25; i++)
{
resource_dir[i] = basePath[i];
}
woule be
strcpy(resource_dir, basePath);
One thing you should notice when using a global variable like this is that if you call getResourcesPath() more than once, you are going to leak resources, if you must use global variables to carry values that need to live as long as the whole program lives, try to make their initialization static, and you can completely avoid using global variables for that, because everything that you declare and initialized in the stack frame of main() will hafe the same lifetime as the program, so you can pass it as parameters to any function that requires them from within main(), if you have many of these variables, create a struct to hold them, and pass the struct across the functions that need these resources, this is a very common technique in fact.
This statements
SDL_Log("%d, %d", &resource_directory, &resource_dir);
outputs as integer values the addresses of global variables resource_directory and local variable resource_dir. Of course their addresses are different.
As for this statement
*resource_directory = *resource_dir;
then it stores the first character of the string pointed to by resource_dir at the address that is stored in pointer resource_directory. However initially resource_directory was initialized by zero as an object with the static storage duration. So the program has undefined behaviour.
I think you mean the following
resource_directory = resource_dir;
That is you wanted that resource_directory would point to the string built in the function.
And there is no sense to use statement
free(resource_dir); <--- If I free here the value goes to crud
necause in this case statement
resource_directory = resource_dir;
also does not have sense.
If resource_directory need to point to the built in the function string then you shall not destroy it.
Take into account that using magic numbers 37 and 25 makes the program unclear and error-prone.
A pointer is a variable that contains a numeric value which happens to be the address of a memory location. For example, a NULL pointer is a variable containing the value 0. Assigning the notion of "isa pointer" to is a way of notifying the compiler of your intended use: that is, you cannot use pointer syntax on non-pointer variables. But until you do use pointer syntax, they more or less behave like normal variables.
int i = 0;
int* p = &i;
int j;
int* q;
j = i; // j has the same value as i
q = p; // q has the same value as p
At the end of the above code, p and q point to the same address. We only use the * syntax when we want to dereference a pointer:
q = p;
*q = *p; // copies the `int` pointed to by `p` to
// the `int` memory location pointed to by `q`,
// which is the same location.
Note that it is possible to nest pointers:
int** pp = &p;
p is int*, so &p is int**.
pp is a numeric value, it is the address of a memory location that contains an int*. *pp means fetch the value at the memory location contained in pp which will retrieve a second numeric value - the value that is in p, which is itself an int* and thus a second address. **pp will retrieve us the integer to which p points.
Your assignment
*resource_directory = *resource_dir;
copies the pointed-to-values, not the addresses.
Since you have tagged your question as C++ I'm going to conclude by offering this alternative implementation:
std::string resource_dir;
void getResourcePath()
{
char *basePath = SDL_GetBasePath();
resource_dir = base_path;
resource_dir += "resources/";
free(basePath);
}
If you need the c-string value of resource_dir subsequently, use resource_dir.c_str().
Alternatively, if you require a C implementation:
char* resource_dir;
void getResourcePath()
{
const char subPath[] = "resources/";
size_t length;
char *basePath = SDL_GetBasePath();
if (resource_dir)
free(resource_dir);
length = strlen(basePath) + sizeof(subPath);
resource_dir = (char*)malloc(length);
snprintf(resource_dir, length, "%s%s", basePath, subPath);
free(basePath);
}
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;
}