1

I am new to structures and I'm trying to do some tutorials to see if i understood well what i've been learning. Here's the code I wrote:

#include <stdio.h>
#include <stdlib.h>

typedef struct variables{
    float Vx;
    float Vy;
    float Vz;
}velocity;

int main(){
    velocity *pv;
    pv = (velocity*)malloc(sizeof(velocity));

    pv[0].Vx = 1;
    pv[0].Vy = 2;
    pv[0].Vz = 3;

free(pv);

return 0;
}

So my questions are 2:

  • Did I allocate the three variables in correct way?

  • Since I'm using the array notation why should I ever write [0] instead of [1] or [2] or so on?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 3
    The array subscripting notation is misleading here. I recommend you use `pv->Vx = 1` etc instead. Also don't cast the return value of `malloc` and unless you feel a strong urge to do so, refrain from `typedef`'ing your `struct`s. Oh, and check whether `malloc` succeeded or returned `NULL`. – 5gon12eder Dec 16 '14 at 20:08
  • @5gon12eder What is your rationale against typedefing structs? – 2501 Dec 16 '14 at 20:11
  • @2501 It adds additional complexity / confusion at no real benefit. In the above example, why have the two names `variables` and `velocity` when `struct velocity` would just do? I also don't like obscuring the semantics of a program by hiding the `struct` in a `typedef`. – 5gon12eder Dec 16 '14 at 20:18
  • @5gon12eder How is it adding to the confusion or complexity. You have either have a struct type or a type. Just use one. *In the above example, why have the two names variables and velocity when struct velocity would just do?* I don't understand this part. `velocity` without the struct prefix is completely identical to `struct velocity`, except you don't have to type `struct`. Less text to type is reducing "complexity". – 2501 Dec 16 '14 at 20:21
  • @2501 You have hit upon one of the major stylistic debates of C. Every programmer will feel **very** strongly about whether you should typedef a struct. They just won't all agree. – Degustaf Dec 16 '14 at 20:26
  • You might consider looking into https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – Jens Gustedt Dec 16 '14 at 20:29

3 Answers3

5

To answer the first question: yes, your code is completely correct. (You even free'd it properly, I'm a bit proud!)

As for the second question, I'm a bit unsure what you mean, but when you call malloc(N * sizeof(type)) where N is some integer (in your case, it would just be 1), you are in essence just creating an array of N elements of type. So pv[0] is the first and only element in this array when N=1, and pv[1], pv[2] etc don't exist.

You should, however, use the syntax pv->Vx instead of pv[0].Vx.

Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • First of all thanks for the answer! I actually thought that sizeof(velocity) would allocate enough space for 3 floats (3*sizeof(float))... I also tried to substitute 0 with 1 and it still works... how is that possible? –  Dec 16 '14 at 20:25
  • `sizeof(velocity)` will allocate enough space for 1 `velocity` variable. This will be enough to hold the 3 floats that make up a `velocity`. As for `pv[1]` working, it means yuou got lucky and were allowed to access that memory. – Degustaf Dec 16 '14 at 20:29
  • `pv[1]` is accessing memory right after the end of the array. This leads to so-called *undefined behavior*, which means that what happens is completely up to the compiler and/or operating system what to do. In your case, you got lucky, but your program could just as well have crashed. – Frxstrem Dec 16 '14 at 20:31
3

Your code is correct, but the syntax you are using is a bit odd. The operator [n] means: Take the pointer's address (in your case the value in pv), increment it by n, and dereference it. Since you are not incrementing the address (n = 0), you can just dereference it. You do this with *pv, or simply with pv->. You only need the [] operator when you have allocated more than one struct, and want to set the address to one of these structs. pv[3] would then be the same as *(pv+3). But you first have to allocate more space if you want to use a pointer as an array:

malloc(sizeof(velocity) * 4)

Philipp Murry
  • 1,660
  • 9
  • 13
  • Thanks for accepting my answer. I found a little mistake: It should be `malloc(... * 4)` when we want `pv[3]` to be valid (because like any array, it goes from 0 to 3, which sums up to 4 elements). – Philipp Murry Dec 16 '14 at 21:28
2
  1. Yes, you used your variables in proper way.

  2. in your code, you've only allocated memory for one instance of the variable. so, it's same if you write pv[0].Vx or pv->Vx. If you want to allocate memory for n number of instances, you can use pv[k].Vx, where 0<=k<=n-1.

SideNote: Please do not cast the return value of malloc().

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261