views:

124

answers:

7

Hello. I made a structure like so:

struct ponto {
    int x;
    int y;
    int z;
};

1) Can I initialize the int's with a default value? int var = value; doesn't seem to work, compiler says "syntax error before '=' token" or something of sorts.

2) I need to work with several of these like in a array of structures, but I only know how many I need after the application starts up, after reading a file. How can I malloc this?

Thanks in advance

EDIT: So many answers, I'm grateful. Sadly I can only mark one

A: 

Question #1: If you need to initialize int with a value:

struct ponto p1;
p1.x = p1.y = p1.z = 3;  // initializing with three

Alternatively, if you want to initialize all values to 0, you can use memset like this:

memset(&p1, 0, sizeof(struct ponto));

Question #2: To use malloc:

struct ponto *ps;
ps = (struct ponto *)malloc(N*sizeof(struct ponto));
// where N is your element count.

This will allocate memory to store N elements of type struct ponto. After that, you can initialize its values with:

int initvalue = 3; // assuming you want to initialize points with value 3
for (i=0; i<N; i++) {
    ps[i].x = ps[i].y = ps[i].z = initvalue;
}
Pablo Santa Cruz
I though casting from void* like that was considered bad form in C?
awoodland
@awoodland: Why? What's the GOOD WAY to cast from `void *` in C?
Pablo Santa Cruz
You don't need a cast to go from void* to struct pronto* in C although you would in C++. I might be wrong here, but I thought the reasoning for not writing the (redundant) cast was that since it doesn't do anything useful in correct code ever the only thing it could do would be to hide problems in incorrect code. (E.g. accidentally casting away const in some other example)
awoodland
Agree: you don't **need** to cast in C. But it's considered good practice to do so. If you compile that with a C compiler, you will get a WARNING saying that...
Pablo Santa Cruz
I just ran a quick test with "gcc -Wall -Wextra" (version 4.5) before querying this and it didn't give any warnings at all.
awoodland
http://c-faq.com/malloc/mallocnocast.html and http://c-faq.com/malloc/cast.html have more discussion too. Looks like it's 6 of 1 and half a dozen of the other...
awoodland
I see... Great links. Didn't know the **not including stdlib** problem...
Pablo Santa Cruz
I'd totally forgotten the "explicitly document every conversion" and "if the type changes later you'll get an error" arguments too :)
awoodland
@Pablo: it is **not** considered good practice in C. It's almost universally considered harmful.
R..
Also, your answer **does not initialize** the struct. It assigns to its members. Initialization would be `struct ponto p1 = { 3, 3, 3 };`
R..
@R:agreed!@Pablo:If you would have said that 20 years ago I would have upvoted .Casting is NOT a good practise for malloc.
fahad
A: 

You'e made a structure definition, now you have to create a variable of that structure before you can set the fields:

struct ponto xyz;
xyz.x = 7;

To allocate enough space:

int need_to_have = 24;
struct ponto *pontos = malloc (need_to_have * sizeof(struct ponto));
paxdiablo
+2  A: 

a) You can initalise with

struct pronto p = {1,2,3};

In recent compilers (not sure how portable this is, think it's C99?)

b) You can allocate an array with malloc:

struct pronto *array = malloc(sizeof(struct pronto) * NUMBER);
awoodland
If you don't cast to `struct ponto *`, in C, you'll probably get a warning from the compiler. In C++, this won't compile at all.
Pablo Santa Cruz
From wikipedia: "Under the ANSI C standard, the cast is redundant." http://en.wikipedia.org/wiki/Malloc
awoodland
Your answer (a) has nothing to do with C99. You're confusing initialization with compound literals.
R..
awoodland
A: 
  1. You cannot have "default" values for structure members. Space is not allocated for a structure definition. You're just creating a new type (like the inbuilt int). When you actually define a variable of type ponto, space will be allocated to it.

  2. You can make an educated guess about how many you will need, allocate space for that many (using malloc) and go ahead. If you find that you're reaching the limit, you can use the realloc function to resize your array.

Noufal Ibrahim
+1  A: 

To initialize your structure members to 0, do:

struct ponto foo = { 0 };

To malloc() an array of the right size, do:

struct ponto *arr = (struct ponto *) malloc(COUNT * sizeof(struct ponto));

Don't forget to free() the array when you're done with it.

Frédéric Hamidi
+1 for the demand to `free` the array after usage. One can not say it often enough!
Flinsch
+1  A: 
struct ponto* create_and_init_ponto(int n)
{
    struct ponto* array;
    int i;

    array = (struct ponto*)malloc( n * sizeof(struct ponto) );

    for ( i = 0; i < n; ++i )
    {
        array[ i ].x = 0;
        array[ i ].y = 0;
        array[ i ].z = 0;
    }

    return array;
}
Flinsch
A: 

1) You cannot give a specific structure default values for its elements at the language level, because all variables in C are uninitialized unless you explicitly initialize them (or make them static/external in which case they're zero-initialized). If you design your structs such that all-zeros is a good set of initial values, though, you can always initialize like this:

struct foo myfoo = {0};

The {0} serves as a universal zero-initializer which works for any type.

If you need different defaults, the best way is to use a macro and document that code using your structure must use the macro:

#define FOO_INITIALIZER { 1, 2, 3 }
struct foo myfoo = FOO_INITIALIZER;

2) If you know before you start using any of the struct how many you will need, simply malloc them all once you know the number:

if (count > SIZE_MAX / sizeof *bar) abort();
struct foo *bar = malloc(count * sizeof *bar);

Note the proper idiom for calling malloc and avoiding overflow vulnerabilities.

If you don't know the number you'll need until you start working with them, start out by allocating a decent number, and if you run out, increase the number by a fixed multiple, for example doubling the size is common and easy. You'll want to check for overflows here. Then use realloc.

R..