views:

311

answers:

5
  1. It's known that big local/global variables may cause to a stack overflow. I know that using pointers and allocating space in memory helps to overcome this problem. But is it the only option? What happens if I have (or need) too-many pointers in global scope?

  2. Regarding the stack space: Is a global struct-type variable takes space in the stack, or acts like a pointer? Do I need to create a pointer of a struct variable type in order to reduce the stack load?

  3. Does the following code allocates memory also to the char** variable named BIG?

    // in the header file  
    typedef struct myStruct {  
        BIG[256][256];  
        int baz;  
    } myStruct;
    
    
    // in the c file  
    myStruct* foo;  
    foo = (myStruct*) malloc( sizeof(*foo) ); 
    
  4. How can I easily cast the return value of malloc()? In question #3 I wrote:

    foo = (myStruct*) malloc( sizeof(*foo) );

    But I prefer to write something like:

    foo = (foo) malloc( sizeof(*foo) ); // the compiler reports an error

    Which will ease the pain when editing the code (when changing the type of foo).

English isn't my native language so sorry for any lack of clarity.

+5  A: 
  1. Globals are not created on the stack.

  2. See 1.

  3. Yes.

  4. You can omit the cast:

    foo = malloc( sizeof(*foo) );

anon
+3  A: 

Neil already answered your questions, here are my comments on your 3rd and 4th questions.

Does the following code allocates memory also to the char** variable named BIG?

typdef struct myStruct {
    char BIG[256][256];
    int baz;
} myStruct;

myStruct* foo;

foo = (myStruct*) malloc( sizeof(*foo) );

(I fixed the error in BIG's type.) This will allocate space for BIG, although BIG is not of type char **. BIG is of type "array [256] of array [256] of char". In value contexts, it is equivalent to "pointer to array [256] of char".


How can I easily cast the return value of malloc()? In question #3 I wrote:

foo = (myStruct*) malloc( sizeof(*foo) );

But I prefer to write something like:

foo = (foo) malloc( sizeof(*foo) ); // the compiler reports an error

You're almost correct in what you want to do, but the right way requires even less typing! The most idiomatic, easy to read, and "type-change safe" way is:

#include <stdlib.h>
foo = malloc(sizeof *foo);

Or more generally,

#include <stdlib.h>
T *foo = malloc(size * sizeof *foo);

No casts are needed, since malloc() returns void *, which can be converted to any pointer type back and forth without any loss of information. Note that this form does not use the type of foo in the malloc() call, so it is type-agnostic. Also, sizeof operator doesn't need parentheses if it's used on an object (but they're needed if it's used on a type).

Alok
+1  A: 

If you really need to cast malloc's return code (are you using C++ compiler?), you can try

foo = (typeof(foo))malloc(sizeof(*foo));

Or even make a macro for it:

#define NEW(A) do {A = (typeof(A))malloc(sizeof(*A));} while (0)
...
NEW(A);

typeof is GCC extension.

qrdl
I can't find `__typeof__` in my ANSI C document. Do you have a reference?
Alok
I think that must be ANSI C 99?
Blank Xavier
I can't find it in n1256. gcc man page says this about `-ansi` though: *The alternate keywords `__asm__`, `__extension__`, `__inline__` and `__typeof__` continue to work despite '`-ansi`'. You would not want to use them in an ANSI C program, of course, but it is useful to put them in header files that might be included in compilations done with '`-ansi`'.*
Alok
Didn't find it in C99 draft (http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf), but search for `__typeof__ C99` produces many hits suggesting that `__typeof__` is standardised
qrdl
<code>__typeof__</code> is the alternate spelling of the GCC-specific typeof operator, used when GCC is in -ansi mode, as pointed out by @alok above. It is not standard in any sense.
Derrick Turk
+1  A: 

1 and 2: File scope (global) variables have static extent, meaning that they are stored differently from local (auto) variables, and should not cause stack overflow. Frankly, if you're overflowing the stack because your (local) variables are too big or you have too many of them, or if you regularly exhaust memory from the heap, then you need to take a step back and rethink your design.

3 and 4:

The idiomatic way to use malloc() is

T *p = malloc(sizeof *p * number_of_elements);

In your case, you would call it as

myStruct *foo = malloc(sizeof *foo);

or

myStruct *foo;
...
foo = malloc(sizeof *foo);

Unless you are working with a very old (pre-C89) compiler, or you're compiling this code as C++ (in which case you should be using new instead of malloc(), you do not need to cast the result of malloc(), and in fact the practice is discouraged.

John Bode
+2  A: 
  1. They're 'elsewhere'. If you ever find a need to have so many globals you run into issues, your source code would be a mess so you refactor it. Or you buy a bigger machine.

  2. Globals are not created on the stack.

  3. Yes, it will create space for the entire struct. However: your BIG member is NOT a char**. Its type is char [256][256] (Assuming you were just missing the 'char' in your question)

  4. In C, you do not need to cast the return value of malloc. a void* is assignable to any kind of pointer. So just do

    foo = malloc( sizeof(*foo) );

Note that foo is a pointer, foo = (foo) malloc( sizeof(*foo) ); makes little sense, as in this case foo is a variable, not a type.

nos