Pointer Initialization Within A Struct

This is a discussion on Pointer Initialization Within A Struct within the C Programming forums, part of the General Programming Boards category; Hello, If the following is valid:- Code: typedef struct { int a; int b; char *name; } thing; thing g_thing ...

  1. #1
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262

    Question Pointer Initialization Within A Struct

    Hello,

    If the following is valid:-
    Code:
    typedef struct {
        int a;
        int b;
        char *name;
    } thing;
    
    thing g_thing = { 1, 2, "Hello" };
    Why isn't:-
    Code:
    typedef struct {
        int a;
        int b;
        int *array;
    } thing;
    
    thing g_thing { 1, 2, { 3, 4, 5 } };
    As the string literal in the first example effectively points to the area of memory used to store an array of chars, why doesn't the use of braces in the second example do the same for the array of ints? Are string literals a special case?

    I would like to be able to do what is described in the second example so that I don't end up with wave after wave of constants that get assigned into structs and are never referred to after that.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, string literals is a special case, because it is the C language's way to form a string.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Because a pointer is not the same thing as an array. You can have an array and initialize that

    Code:
    typedef struct {
        int a;
        int b;
        int array[3];
    } thing;
    
    thing g_thing = { 1, 2, { 3, 4, 5 } };
    String literals are an exception. They already are somewhere in the memory and you just point a pointer to that.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262
    Bummed.
    Ah well, guess I can try to structure my constant data in a slightly larger form...

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    To add to anon's suggestion: If you have a variable number of elements in your list of integers [array/pointer], then you may find that forming a temporary variable is the only option. If you have a compiler that supports variable number of arguements to macros (gcc does in recent versions at least, and I think the latest MS compilers also does), you could possibly use that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262
    Resolved by instead using:-
    Code:
    typedef struct {
        int a;
        int b;
        int *array;
    } thing;
    
    int g_thing1array[3] = { 3, 4, 5 };
    thing g_thing1 = { 1, 2, g_thing1array };
    One extra line isn't that bad I suppose.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    /* First byte: Length. Following bytes: Opcode bytes. */
    #define MAKE_INSTR(nm, ...) static const u8 OPCODE_##nm[] = { __VA_ARGS__ }
    MAKE_INSTR(INVD,   2, 0x0f, 0x08);
    MAKE_INSTR(WBINVD, 2, 0x0f, 0x09);
    MAKE_INSTR(CPUID,  2, 0x0f, 0xa2);
    MAKE_INSTR(RDMSR,  2, 0x0f, 0x32);
    MAKE_INSTR(WRMSR,  2, 0x0f, 0x30);
    MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
    MAKE_INSTR(HLT,    1, 0xf4);
    MAKE_INSTR(INT3,   1, 0xcc);
    MAKE_INSTR(RDTSC,  2, 0x0f, 0x31);
    
    static const u8 *opc_bytes[INSTR_MAX_COUNT] = 
    {
        [INSTR_INVD]   = OPCODE_INVD,
        [INSTR_WBINVD] = OPCODE_WBINVD,
        [INSTR_CPUID]  = OPCODE_CPUID,
        [INSTR_RDMSR]  = OPCODE_RDMSR,
        [INSTR_WRMSR]  = OPCODE_WRMSR,
        [INSTR_VMCALL] = OPCODE_VMCALL,
        [INSTR_HLT]    = OPCODE_HLT,
        [INSTR_INT3]   = OPCODE_INT3,
        [INSTR_RDTSC]  = OPCODE_RDTSC
    };
    Here's a snippet of xen/arch/x86/hvm/svm/emulate.c that I originally wrote, which uses variable length array to describe differnet instruction formats.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    cas
    cas is offline
    Registered User
    Join Date
    Sep 2007
    Posts
    975
    Thankfully C99 has added compound literals which allow you to do this the way you originally tried (although not with that precise syntax). Unfortunately, C99 isn't widespread. But if you can use it, here's what it looks like:
    Code:
    typedef struct {
      int a;
      int b;
      int *array;
    } thing;
    
    thing g_thing = { 1, 2, (int[]){ 3, 4, 5 } };
    One thing to be careful of is that compound literals that are inside of blocks have automatic storage duration. So unlike string literals, pointers to them become invalid when the block is exited. This isn't an issue with file-scope (global) compound literals.

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    Quote Originally Posted by SMurf View Post
    Resolved by instead using:-
    Code:
    typedef struct {
        int a;
        int b;
        int *array;
    } thing;
    
    int g_thing1array[3] = { 3, 4, 5 };
    thing g_thing1 = { 1, 2, g_thing1array };
    One extra line isn't that bad I suppose.
    Not a good very good solution.
    The local array will go out of scope at the end of the function and then your pointer will point at undefined.

    Quote Originally Posted by cas View Post
    Thankfully C99 has added compound literals which allow you to do this the way you originally tried (although not with that precise syntax). Unfortunately, C99 isn't widespread. But if you can use it, here's what it looks like:
    Code:
    typedef struct {
      int a;
      int b;
      int *array;
    } thing;
    
    thing g_thing = { 1, 2, (int[]){ 3, 4, 5 } };
    One thing to be careful of is that compound literals that are inside of blocks have automatic storage duration. So unlike string literals, pointers to them become invalid when the block is exited. This isn't an issue with file-scope (global) compound literals.
    I doubt that's valid C. I only get syntax errors.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,448
    Quote Originally Posted by Elysia
    I doubt that's valid C. I only get syntax errors.
    After I placed the last line in the main function, it compiled without any errors or warnings (besides a benign "unused variable" warning) for me. Perhaps you forgot to turn on C99 mode?
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    But Visual Studio does not support C99.
    It doesn't matter what I do, this code...
    Code:
    typedef struct
    {
    	int a;
    	int b;
    	int* array;
    } thing;
    
    int main()
    {
    	thing g_thing = { 1, 2, (int[]){ 3, 4, 5 } };
    }
    ...gives one syntax error in C and a slew of syntax errors in C++.
    Last edited by Elysia; 02-08-2009 at 08:09 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,448
    Quote Originally Posted by Elysia
    But Visual Studio does not support C99.
    SMurf has not given any indication in this thread that he/she must use a Microsoft compiler or some other compiler that lacks support for C99, while cas explicitly stated that the code was written with respect to C99.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,452
    Of course. I was referring to your...
    Perhaps you forgot to turn on C99 mode?
    ...quote. Since VS does not support C99, this is something I cannot do.

    Still, I am skeptical, because so far as I know, casting to an array of any type is illegal.
    Are you sure this is allowed and not some exception?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,262
    Quote Originally Posted by matsp View Post
    Code:
    /* Loadsa crazy #define stuff */
    To me this demonstrates that you have skillz.
    I've never really gotten the hang of preprocessing myself, but I have seen similar in things like MAME. It may go some way to helping me tidy this up. Do you happen to know a good reference?

    cas: I had a feeling that C99 might have fixed this "bug", however Elysia's telepathy rides again: I am using MSVC and so am stuck in the dark ages for now.

    Elysia: I would only use this for global scope. This is to sort out all of the hard-coded data structures that my program (a script interpreter) would use.

    My original point was to underline that while I think that C is an amazing language, there does seem to be a few easily-fixable flaws in its rules. Still, I guess that's what they made Java for, right?

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Not sure I know of any good reference for preprocessor stuff.

    This described the Visual Studio preprocessor stuff.
    http://msdn.microsoft.com/en-us/library/y4skk93w.aspx

    If you have SPECIFIC questions on how to do something in particular, then I suggest you ask.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 12-03-2008, 02:10 AM
  2. pointer problem or so...
    By TL62 in forum C Programming
    Replies: 19
    Last Post: 01-12-2008, 10:45 PM
  3. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 03:25 AM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 08:32 AM
  5. Passing pointers between functions
    By heygirls_uk in forum C Programming
    Replies: 5
    Last Post: 01-09-2004, 05:58 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21