struct element {
int val;
int z;
};
typedef struct element ELEM;
Look at this example:
int main()
{
ELEM z;
z =
Declaring a pointer doesn't create anything but a pointer. Gotta have something for it to point to, which is what malloc
gives you.
Alternatively, you could have created the struct on the stack (a.k.a. "automatic storage"):
ELEM z;
ELEM *p = &z;
(*p).val = 3; // Also could be written as p->val = 3;
printf("%d",(*p).val);
BTW, your pointer code has an error, in that it leaks (i.e. loses track of) the first allocated struct:
ELEM *p;
p = (ELEM*)malloc(sizeof(ELEM));
(*p).val = 3;
p = (ELEM*)malloc(sizeof(ELEM)); // <- leak here: pointer to old struct lost.
printf("%d",(*p).val);
Deleting the second malloc
fixes the problem. A full, fixed-up version that looks more like code you'd see in use:
ELEM *p = (ELEM*)malloc(sizeof(ELEM));
p->val = 3;
printf("%d\n", p->val);
free(p);
Every malloc
should have a free
, unless your program releases it memory by terminating. And even then, it's nice to have the free
.
Let's try to visualize it using your struct
definition.
struct element
{
int val;
int z;
};
typedef struct element ELEM;
When you declare a variable of this type, it is allocated in memory in a safe place, that is, the implementation won't use this memory for anything else while it is in scope.
ELEM e;
val z
e[ int ][ int ]
When you declare a pointer to a variable of this type and don't initialize it, it is pointing to some undefined location.
ELEM *pE;
val z
pE[ int ][ int ]
This pointer, even though it has been initialized still considers itself pointing to an ELEM
. The actual address that it's pointing to could be "harmless", that is, you could actually use it and not cause any run time problems. However, if you're lucky, if you use it you'll get a run time error, such as a segmentation fault. This happened because you've accessed a memory location that is illegal. If you're writing, you could write over code or data and corrupt it.
pE
must point to a safe memory location, one that has been allocated for a ELEM
:
pE = &e;
val e
pE -> e[ int ][ int ]
pE
is now pointing to e
. It can safely read and write from and to this memory location without any danger.
You can also allocate memory personally for pE
using malloc:
pE = malloc(sizeof(*pE);
You only need to use malloc
if you intend to dynamically allocate memory. Otherwise, your pointer must point to something. If you intend to use your pointer when it doesn't point to valid memory, it is undefined behavior.
struct Elem
{
int val;
};
int main() {
struct Elem elem;
struct Elem* ptr; // can't use pointer, points to nothing
ptr = &elem; // good, points to elem
ptr->val = 5;
printf("%d", ptr->val);
ptr = malloc(sizeof(struct Elem)); // good, points to object on the heap
ptr->val = 10;
printf("%d", ptr->val);
free(ptr);
return 0;
}
The pointer is only the address of the object in C/C++, not the object itself. In a 32-bit system, its length is always 4 bytes. When you create a pointer, it will refer to a invalid address if you don't initialize it or allocate memory for it. So you must dynamically create the object by calling malloc
(in C++, you can use new
keyword), then it can refer to the address of the created object.
ELEM elem; //This will create the object at stack.
ELEM* pElem; //This just create an invalid poiter which point to unknown address
pElem = &elem; //This initialize the pointer which point to the address if "elem" above
pElem = (ELEM*)malloc(sizeof(ELEM)); //This create a new memory which contain the object "ELEM" and pElem will point to the address of the object
In your first example,
int main() {
ELEM z;
z = 6;
printf("%d",z);
}
You are creating a z
Elem
on the stack. This is a very efficient operation, and the language will manage the memory allocated to z
for you - that is when z
goes out of scope it will automatically be freed. In contrast, your second example,
ELEM *z;
Creates a pointer on the stack (which is a 32-bit value on a 32-bit OS, and a 64-bit value on a 64-bit OS) but does not allocate any elements. That is the purpose of the malloc
routine, to allocate memory on the heap. You may point to one (as in your example), or many different elements dynamically through your pointer into the heap and you must free memory you allocate.