Thread: Variable initialization and assignment question

  1. #1
    Registered User
    Join Date
    Aug 2015
    Posts
    9

    Variable initialization and assignment question

    Hello all,

    I would like to ask for some little explanation.

    Suppose I have a following code:
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    
    typedef struct {
            char* firstName;
            char* lastName;
            unsigned int age;
            char gender;
            double hourlySalary;
        }Worker;
    
    
    Worker* initperson(char*, char*, unsigned int, char, double);
    
    int main(void){
    
        Worker *emp; 
        emp = initperson("David", "Jhonson", 27, 'M', 1578.45);
           
        printf("%s %s age: %d, gender: %c, salary: %.2lf\n",
                emp->firstName, emp->lastName, emp->age, emp->gender, 
                emp->hourlySalary);
        
        return 0;    
    }
    
    
    Worker* initperson(char* first, char* last, unsigned int Age, char gend, double salary){
    
        Worker* person = malloc(sizeof(*person));
    
        if(person != NULL){
            person->firstName = first;
            person->lastName = last;
            person->age = Age;
            person->gender = gend;
            person->hourlySalary = salary;
        }
        
        return person;
        
    }
    My question is about this line:
    Code:
    Worker* person = malloc(sizeof(*person));
    How this line should be read?

    Just've seen some example at old stack-exchange thread and tried to reproduce it with my code.

    I mean, normally I would write something like:
    Code:
    Worker* person;
    person = malloc(sizeof(Worker)); 
    
    
    // possibly adding casting prior malloc, 
    // like this: (Worker*)malloc(sizeof(Worker));
    But when this have written in a single line, I can't actually get of what actually happens.


    It looks like:
    Firstly the pointer of Worker type struct is created (still it is not initialized)
    Secondly this un-inited pointer is used (or more exactly: a sizeof command evaluates how much memory has been taken by "*person", then this value is used by "malloc" function to create an empty struct in the memory + pass pointer to it.

    Anyway, your help will be highly appreciated.

    Thanks a lot in advance.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Let's start by examining what is sizeof and what does it do:
    Quote Originally Posted by C11 Clause 6.5.3.4 Paragraph 2
    The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
    From the above we glean a few facts relevant to your question:
    • sizeof is an operator, not a function.
    • The operand of sizeof could be an expression, but it could also be the name of a type, in parentheses.
    • The operand of sizeof is not evaluated unless its operand is of a variable length array type.

    So, we see that in this statement:
    Code:
    Worker* person = malloc(sizeof(*person));
    The operand of sizeof is an expression, i.e., (*person). The parentheses are actually optional because this is an expression not a type name. But the point is that person is declared to be a pointer to Worker, so *person is of type Worker. Worker is a struct type, not a variable length array type, hence the operand of sizeof is not evaluated. Therefore, we can write sizeof(*person) even though person is being declared at that point and is in the midst of being initialised: *person is simply not evaluated.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Aug 2015
    Posts
    9
    Yep, you did it again ))) My brain was challenged ^_^ (kind of compliment)

    Still, would like to ensure I got your answer right.

    First, as it turns out I need to work harder on my C terminology. Next time I'll try to be more precise.

    Second:

    What did you mean by saying:
    Worker is a struct type, not a variable length array type, hence the operand of sizeof is not evaluated.

    And then again:
    ... *person is simply not evaluated.
    Does "evaluation" means: "To check if the value is True or False?"

    Third:

    Regard to this line:

    Code:
    Worker* person = malloc(sizeof *person);
    If I tear-down this line into separate chunks, we'll get following picture:

    *person ---> is an expression (as you've said) which consists of '*' indirection operator and leads to pointer dereferencing.
    Another words, according to Deitel's book:
    returns the value of the object to which its operand (i.e., a pointer) points
    Then we have the sizeof operator, that according to your citation of "C11 Clause" makes the following:
    The size is determined from the type of the operand.

    So a sizeof doesn't "care" about actual value which pointer refers to, it cares about:"how much memory this datatype takes?" Furthermore (and this is the thing that drove me crazy):

    The 'sizeof' and '*' and '=' have "right to left associativity".

    So I've asked myself: "how malloc can allocate memory for something that has no size".

    But, in our case Worker datatype has been defined, and since sizeof cares about size of datatype, everything worked out.
    Is that right conclusion?

    Finally, the equivalent code would be:
    Code:
     Worker* person = malloc(sizeof (Worker));
    BTW, what about casting prior malloc? Is this necessary?

    I mean if the above line would look like this:
    Code:
     Worker* person = (Worker *)malloc(sizeof(Worker));
    Again thanks for your time.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by bravoelf
    Does "evaluation" means: "To check if the value is True or False?"
    No, to "evaluate" the expression is to execute the code corresponding to it at run time (the compiler may do optimisations such that the code that you wrote is compiled into code that is not exactly equivalent to what you wrote, but has the same essential meaning and net effect). Since the operand is not evaluated, the compiler would not even generate code for the expression, e.g., it would figure out that say, sizeof(*person) is 32, and hence generate code equivalent to:
    Code:
    Worker* person = malloc(32);
    rather than code equivalent to dereferencing the pointer named person.

    Quote Originally Posted by bravoelf
    So a sizeof doesn't "care" about actual value which pointer refers to, it cares about:"how much memory this datatype takes?"
    Yes. In the case of a variable length array it does have to care because the amount of memory a variable length array takes is determined at run time, but otherwise no.

    Quote Originally Posted by bravoelf
    But, in our case Worker datatype has been defined, and since sizeof cares about size of datatype, everything worked out.
    Is that right conclusion?
    Yes.

    Quote Originally Posted by bravoelf
    what about casting prior malloc? Is this necessary?
    Unless you require compatibility with C++, you should not cast the return value of malloc: there is an implicit conversion from void* to a pointer to object that, so no casting is necessary, and if you do cast, you would suppress a warning that is likely to result from forgetting to #include <stdlib.h>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Aug 2015
    Posts
    9
    Thanks a lot Laserlight, you're AWESOME! ^_^

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Variable initialization
    By cnewbie1 in forum C++ Programming
    Replies: 5
    Last Post: 10-24-2011, 11:24 AM
  2. assignment vs initialization
    By KIBO in forum C++ Programming
    Replies: 3
    Last Post: 11-03-2010, 09:46 AM
  3. Replies: 10
    Last Post: 03-28-2010, 01:35 AM
  4. Initialization and assignment
    By rajesh1978 in forum C++ Programming
    Replies: 7
    Last Post: 03-18-2009, 08:13 AM
  5. Assignment vs. Initialization
    By arrgh in forum C Programming
    Replies: 6
    Last Post: 05-06-2008, 03:08 AM