Thread: sizeof for an extern array

  1. #1
    Registered User
    Join Date
    Mar 2020
    Posts
    3

    sizeof for an extern array

    I have 2 files, one .cpp with an array of c strings
    Code:
    char strings[][64]={
    "One",
    "Two",
    "Three"};
    in another .cpp file I have

    Code:
    extern strings[][64];
    In this file I need to know the number of strings but if I use:
    Code:
    sizeof(strings)/sizeof(strings[0])
    the compiler gives me an "invalid application of sizeof to incomplete type char [][64]"

    how can I calculate the number of strings in this array declared extern?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    928
    You can't take the sizeof an incomplete type.
    You can add something like this after your array definition:
    Code:
    const int strings_size = sizeof strings / sizeof strings[0];
    and then in the other file
    Code:
    extern const int strings_size;
    Alternatively you could use a macro in a header (which you would need to keep updated).
    Or you could include a sentinel value at the end of the array so the size isn't needed.
    If you want the truth to stand clear before you, never be for or against. - Sent-ts'an

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,730
    Is this supposed to be an array of string constants? If so, then the best solution would be to define them inline in a header file:
    Code:
    inline const char strings[][64] = {
        "One",
        "Two",
        "Three"
    };
    then include this header file in each of the source files that need this array of string constants. You would need to compile with respect to C++17 or later though.

    If this really is an array of string variables instead, then I would ask you to re-consider if you really need such global state. If you do, you can still take the above approach, though an unwary reader might mistake them as constants, so there might still be some benefit to using the old extern approach with the calculated size as john.c suggested (or maybe you can warn the unwary reader by writing a comment to explain the global state).

    EDIT:
    Quote Originally Posted by john.c
    Alternatively you could use a macro in a header (which you would need to keep updated).
    If you want to do it that way though, I would suggest a modern C++ alternative:
    Code:
    inline std::array<char[64], 3> strings{
        "One",
        "Two",
        "Three"
    };
    Again, because of the inline variable, this requires C++17 or later, but this has the advantage of strongly associating the size with what it is the size of (i.e., strings.size()), while thanks to inlining there should be no function call penalty. It also has the advantage of a compile error should you increase the number of elements in the initialiser while forgetting to update the size, whereas with a macro this mistake could pass silently at compile time.
    Last edited by laserlight; 03-29-2020 at 02:41 PM.
    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

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    928
    Now that I think about it, my solution is pretty bad. I also forgot this was the C++ forum, so I didn't consider std::array.

    It does make sense that they are probably constants. For the string constants you may as well get rid of the [64] and make them pointers. A sentinel is even more feasible in that case as nullptr:
    Code:
    // file1.cpp
     
    // It's global, so give it a big name and capitalize it.
    const char *StringConstants[] = {
        "one",
        "two",
        "three",
        nullptr
    };
     
    // file2.cpp
     
    extern const char *StringConstants[];
     
    //...
        for (const char **s = StringConstants; *s; ++s)
            std::cout << *s << '\n';
    Last edited by john.c; 03-29-2020 at 04:36 PM.
    If you want the truth to stand clear before you, never be for or against. - Sent-ts'an

  5. #5
    Registered User
    Join Date
    Apr 2019
    Posts
    76
    Quote Originally Posted by laserlight View Post
    Is this supposed to be an array of string constants? If so, then the best solution would be to define them inline in a header file:
    Code:
    inline const char strings[][64] = {
        "One",
        "Two",
        "Three"
    };
    then include this header file in each of the source files that need this array of string constants. You would need to compile with respect to C++17 or later though.

    If this really is an array of string variables instead, then I would ask you to re-consider if you really need such global state. If you do, you can still take the above approach, though an unwary reader might mistake them as constants, so there might still be some benefit to using the old extern approach with the calculated size as john.c suggested (or maybe you can warn the unwary reader by writing a comment to explain the global state).

    EDIT:

    If you want to do it that way though, I would suggest a modern C++ alternative:
    Code:
    inline std::array<char[64], 3> strings{
        "One",
        "Two",
        "Three"
    };
    Again, because of the inline variable, this requires C++17 or later, but this has the advantage of strongly associating the size with what it is the size of (i.e., strings.size()), while thanks to inlining there should be no function call penalty. It also has the advantage of a compile error should you increase the number of elements in the initialiser while forgetting to update the size, whereas with a macro this mistake could pass silently at compile time.
    thanks for learning me new ways of C++,going to try string constants next time instead of string variables,must be better compiled into constants readonly section than accidently write over it with pointer gone astray
    you tell me you can C,why dont you C your own bugs?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 12-09-2010, 02:33 PM
  2. sizeof array
    By MAx12345 in forum C Programming
    Replies: 2
    Last Post: 07-22-2008, 02:01 AM
  3. sizeof array?
    By AtFantasy in forum C Programming
    Replies: 3
    Last Post: 06-27-2003, 05:30 PM
  4. sizeof(array) returns differnt values for same array?
    By Diamonds in forum C++ Programming
    Replies: 6
    Last Post: 02-02-2003, 04:27 PM
  5. extern array definition
    By achacha in forum C Programming
    Replies: 2
    Last Post: 08-05-2002, 02:10 PM

Tags for this Thread