Reputation: 41
I am learning about Dynamic Memory Allocate now and it's hard to understand, especially when the lecturer mentioned about DMA and structure using pointer.
First, at the line 1 in my code, i get confused what "&ptr->eno" means. we initiate ptr as a pointer so it means ptr hold the address of the memory we reserved, lets say ptr hold the address 2046, is that "&ptr->eno" means writing value to the address of 2046 it point to?
Second, at the line 2, how i can print out the value, cause "ptr->eno" contains value "2046" than when i print it out, it gonna give me the number 2046, not the value i try to stored in the memory location 2046.
My code was copied from the lecture note, i tried to run it on Visual studio, it crashed after i input the values. I am so new with C, my assumption may looks stupid and painful to understand. if you can't understand my explanation, please tell me how to use pointer with structure, may be i can figure out my mistake. Thank you
#include<stdio.h>
#include<stdlib.h>
struct emp
{
int eno;
char ename[20];
float esal;
};
void main()
{
struct emp* ptr;
ptr = (struct emp*)malloc(sizeof(struct emp));
if (ptr=NULL)
{
printf("out of memory error");
}
else
{
printf("enter the value of employee: \n");
scanf_s("%d%s%f", &ptr->eno, ptr->ename, &ptr->esal); // line 1
}
printf("the name is: %s \t the number: %d \t the salary: %f", ptr->ename, ptr->eno, ptr->esal); //line2
}
Upvotes: 0
Views: 177
Reputation: 399833
This:
if (ptr=NULL)
doesn't do what you want. You want the comparison operator ==
, not the assignment operator =
. This will always set ptr
to NULL, making the rest of the code have undefined behavior (which often leads to crashes in practice). Enabling, and looking at, compiler warnings is a very good way of avoiding this problem.
For the actual question, &ptr->eno
means "the address of the field eno
in the struct pointed to by ptr
". In practice it will evaluate to the value of ptr
, plus the offset from the start of the structure to the field eno
, which in this case will be 0 since eno
is the first field.
Furthermore, the printf()
should of course be inside the else
, since you can only run that if ptr
is not NULL.
And, importantly: you must provide a buffer size for the string to scanf_s()
.):
Unlike
scanf
andwscanf
,scanf_s
andwscanf_s
require the buffer size to be specified for all input parameters of typec
,C
,s
,S
, or string control sets that are enclosed in[]
. The buffer size in characters is passed as an additional parameter immediately following the pointer to the buffer or variable.
So, it should be:
const int num = scanf_s("%d%s%f", &ptr->eno, ptr->ename, (unsigned int) sizeof ptr->ename, &ptr->esal);
if (num == 3) // All conversions succeeded, we can rely on them
{
printf("the name is: %s \t the number: %d \t the salary: %f", ptr->ename, ptr->eno, ptr->esal); //line2
}
And you should check its return value, otherwise you risk using non-initialized variables if the input fails for some reason.
Note that the size of the buffer seems to be specified as unsigned int
, and not size_t
, which is ... not optimal in my point of view so the cast is needed.
By the way, "DMA" typically means "direct memory access" and has nothing to do with this; that was confusing me for a while.
Upvotes: 4
Reputation: 34585
Assuming that
if (ptr=NULL)
was a typo (since the subsequent "it crashed after i input the values" could not have happened), there is a fault here:
scanf_s("%d%s%f", &ptr->eno, ptr->ename, &ptr->esal);
is missing the required size argument for %s
scanf_s("%d%s%f", &ptr->eno, ptr->ename, 20, &ptr->esal);
or instead of hard coding, perhaps
scanf_s("%d%s%f", &ptr->eno, ptr->ename, (unsigned)sizeof ptr->ename, &ptr->esal);
Upvotes: 4
Reputation: 21965
It is not a good practice to cast the output of malloc
(check [ this ] ), the simplest way to do it would be
struct emp *ptr;
ptr = malloc(1 * sizeof *ptr);
Then, ==
is used for equal to logical comparison, so
if (NULL == ptr)
/* = changed to ==, also put the value first which will help you easily
* fix accidental omission of the second =
*/
{
printf("out of memory error");
exit(1); // Exiting with a non-zero status
}
Note This should be taken as a supplement to [ this ] answer
Upvotes: 1