Ok, I'm not going to give you a 1on1 pointer guide (I'm not planning to write a book), but here's the quick guide, based on your assumptions/questions:
- "
int *pInt: this is an array of type int that's in the struct"
It Might be, pInt is a pointer to an integer. It needn't be an array. An array is a pointer, but a pointer isn't always an array. Right, an array is -of course- an array, but the way you access it in C is through either an array variable or a pointer.
The differences are clearly explained here
Basically: an array is a continuous block of memory, an array variable often (well, always save for 3 cases listed on the page I linked to above) decays into a pointer. Read the why's and how's, to get a clear understanding of the differences and similarities between pointers and arrays.
If you understand why one of the following snippets is not allowed and the other one is, you're there:
char *str = "Read only";
printf("%c\n", str[2]);//prints a from (0=>r, 1=>e, 3=> a...)
str[2] = 'q';//ILLEGAL
//BUT:
char str[] = "Read only";
str[2] = 'q';//perfectly legal...
printf("%c\n", str[2]);//prints q!
Why is this? Simple. In both cases, the literall "Read only" is stored in read-only memory. The difference is that, by assigning this string to a pointer(char *str), we're assigning the read-only mem address to the variable, so we can't change the memory it points to (that's what read-only means).
In the second case, the string literal is stored in the same read-only memory, but because we're assigning it to an array, it's values are copied to newly allocated stack memory, and we can write to that.
So, a pointer points to some chunk of data in memory. This memory can be writable or not, the memory address could be the address of part of an array or it could be a single int (like it is in your case), You could even have pointers that point to several pointers, and each of these pointers could, essentially, point to different places in memory (ie not a continuous block).
Anyway, consider this:
int i = 123;
int arr[3] = {1,2,3};//array
int *iPtr = &i;//iPtr contains the mem address of i
printf("%d\n", *iPtr);//prints 123
iPtr = arr;//iPtr points to the same as arr (note no & operator)
printf("%d\n", *iPtr);//prints 1
//now probably a mindfuck for you now, but:
printf("%d\n", *(iPtr+1));//prints 2!
The last bit is just to show what pointers are: it's a location in memory, big enough to accomodate an int, so if I take that space in memory, and do +1, I'm accessing that chunk of memory right next to the one my pointer points to. In memory, this might look something like this:
| 0x0f0 | 0x0f2 | 0x0f4 | 0x0f6 | //mem address
| *iPtr | iPtr + 1 | iPtr + 2 | iPtr + 3 | //access via pointer
That's why pointers can be dangerous. In the code above, iPtr points to the first of 3 ints (as defined in the arr array), but if I access *(iPtr+4), I'm accessing memory that is out of bounds. You are accessing memory that was not claimed/initialized, or owned by something else. This can, and probably will lead to unexpected behaviour... but I have seen this used to get some extra randomization...
- "
newStruct *createMyStruct: a function that's named createMyStruct. createMyStruct is a pointer that points to newStruct and create a copy of the newStruct."
You lost me here, this is a function definition. The function is indeed called createMyStruct, and it returns a pointer to something of the type newStruct. That's it, just like int some_function() is a function that returns an int
- "
newStruct *pStruct: pStruct is the same as createMyStruct (?)"
No, pStruct is a pointer to a newStruct, and pStruct is a function argument, not a function, which createMyStruct is.
On calling free:
You call free on variables that are stored in memory allocated from the heap, when you don't need them anymore. If they go out of scope, you can't free them anymore, so you have to dellocate the memory when you still have a variable that points to it, but you shouldn't deallocate anything you might need later on in the program:
char *str = calloc(11, sizeof(char));
free(str);
//I can't use str here anymore
But:
int main()
{
void some_function();
some_function();
//I can't free str here, mem-leak immanent!
return 0;
}
void some_function()
{
char *str = calloc(11, sizeof(char));
//do stuff, but no calls to free
}
in this case, free(str); should have been the last statement in some_function. If some_function would've been char *some_function() and we'd have written this:
int main()
{
char *return_val = NULL;
char *some_function();
return_val = some_function();
printf("%s was returned by some_function\n", return_val);
//the allocated memory is accessible here
//And it has to be freed before main returns, so:
free(return_val);//deallocate!
return 0;
}
char *some_function()
{
char *str = calloc(11, sizeof(char));
//do stuff, but no calls to free
return str;//return char pointer
}
it ended with return str, then you'd have to call free in the main function, as it has a pointer to the allocated memory.
That's it, in a nutshell...