Advertisement Jump to content
Sign in to follow this  
Satharis

Static const & member arrays

This topic is 1873 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, kind of a two part question here.
 
//HEADER

private:
    static const unsigned int RECEIVE_BUFFER_SIZE;
    static const unsigned int SEND_BUFFER_SIZE;

    static char m_receiveBuffer[];
    char m_sendBuffer[SEND_BUFFER_SIZE];

//CPP FILE

const unsigned int Connection::RECEIVE_BUFFER_SIZE = 8192;
const unsigned int Connection::SEND_BUFFER_SIZE = 8192;
char Connection::m_receiveBuffer[RECEIVE_BUFFER_SIZE] {};
This is probably me just not really understanding the basis of how static is compiled but;

1. Given the above code, my understanding is that m_sendBuffer needs a size definition at compile time so that other files including the header have that information available. Is there any way for me to create a member array like that without new or without placing the definition of the size in the header file?

The only reason I ask that is because std::strings are another common thing I use for header constants, but they take up memory so as far as I know I have to define them inside the cpp file. I find it a little annoying to have to place the int constants in the header and the string constants in the cpp file, so I was searching for a way to have both in the cpp file. Is there no option besides the two I listed?

2. Regarding the static, I don't really get the behavior of what it is doing. Why can I declare it without a stated size while the member array requires it? I technically can remove the line where it zero initializes the receive buffer in the cpp file and it will compile just fine. So what are other files seeing? What is that line with a stated size actually doing? I know arrays are just pointers but wouldn't that mean it essentially is pointing to unallocated memory?

I'm mainly just trying to figure out what the actual behavior here is doing and if terrible things happen if I remove the definition of m_receiveBuffer, which still happily compiles.

Share this post


Link to post
Share on other sites
Advertisement

1: You are correct that people who include your header file need to know how big m_sendBuffer is, and thus you do have to define SEND_BUFFER_SIZE in the header file. I don't think there's a simple way around your problem. You can't define the array size in the cpp file, plain and simple. 

 

2: What you're saying when you declare m_receiveBuffer in the header file is just that there exists a char array that is a static member of the class. You aren't saying where it is or anything else about it, merely that it exists. The compiler will take your word for it and hope that the linker can actually find the definition of that object.  When you define the array in the cpp file, it will need a specific size, because at that point the array is actually created and memory is created for it in the object file. This is in contrast to m_sendBuffer, which is an instance member of your class. Its size must be known because it affects the class definition that it's part of.

 

EDIT: Regarding you saying that you can remove the definition of m_receiveBuffer and your program compiles just fine: I agree that it should compile, but does it link? If so, are you ever referencing m_receiveBuffer? If not, if you reference m_receiveBuffer, do you then get a linker error? I would expect a linker error (some kind of unresolved external symbol error regarding CClass;:m_receiveBuffer).

Edited by Samith

Share this post


Link to post
Share on other sites

1: You are correct that people who include your header file need to know how big m_sendBuffer is, and thus you do have to define SEND_BUFFER_SIZE in the header file. I don't think there's a simple way around your problem. You can't define the array size in the cpp file, plain and simple. 
 
2: What you're saying when you declare m_receiveBuffer in the header file is just that there exists a char array that is a static member of the class. You aren't saying where it is or anything else about it, merely that it exists. The compiler will take your word for it and hope that the linker can actually find the definition of that object.  When you define the array in the cpp file, it will need a specific size, because at that point the array is actually created and memory is created for it in the object file. This is in contrast to m_sendBuffer, which is an instance member of your class. Its size must be known because it affects the class definition that it's part of.

Alright thanks, I think that cleared up most of what I didn't get. While I was reading your reply it kind of popped into my head that the static doesn't actually -belong- to the class and is just scoped by it, and thus nobody else needs to know its actual size since it wouldn't be part of any object instances they create.

EDIT: Regarding you saying that you can remove the definition of m_receiveBuffer and your program compiles just fine: I agree that it should compile, but does it link? If so, are you ever referencing m_receiveBuffer? If not, if you reference m_receiveBuffer, do you then get a linker error? I would expect a linker error (some kind of unresolved external symbol error regarding CClass;:m_receiveBuffer).

You're also correct here, I didn't notice at the time until I read what you said and built the entire thing, I was just changing the file and manually compiling the one file, but yes, it does give a linker error. If I give the definition an empty size it also says it can't allocate size 0 so that behavior makes sense as well.

Share this post


Link to post
Share on other sites

So a little variation on my earlier questioning. Given the following code:
 

// HEADER

static const unsigned int SEND_BUFFER_SIZE = 8192;

static char m_receiveBuffer[RECEIVE_BUFFER_SIZE];

// CPP FILE

char Connection::m_receiveBuffer[RECEIVE_BUFFER_SIZE];

Is there any fundamental difference between making the declaration:

static char m_receiveBuffer[RECEIVE_BUFFER_SIZE];

VS

static char m_receiveBuffer[];

Also, this manages to compile and run successfully, despite my IDE actually giving an error that the type isn't defined in the cpp file:

// HEADER

static const unsigned int SEND_BUFFER_SIZE = 8192;

static char m_receiveBuffer[];

// CPP FILE

char Connection::m_receiveBuffer[];

Is this undefined?

Edited by Satharis

Share this post


Link to post
Share on other sites

I think 

static char m_receiveBuffer[RECEIVE_BUFFER_SIZE];

and

static char m_receiveBuffer[];

are the same, though the first version gives a bit more info to the compiler which might be used to generate warnings (EDIT: also, the first case can be used in sizeof). It's totally legal to index outside of array bounds in C++, so the array length in the declaration isn't particularly meaningful. This is similar to passing an array type as a parameter to a function:

// these functions all have the same signature, according to the compiler
int foofunc(int myArray[10])
{
    // etc
}

int foofunc(int myArray[])
{
    // etc
}

int foofunc(int myArray[2])
{
    // etc
} 

As for your second question: I honestly am not 100% sure what you get if you define your array like that. My guess is that it's just a zero length array at some location in your executable, and when you try and index into it you're just going to be reading/writing arbitrary memory (ie: undefined behavior, as you suspected). I can't think of any reason why you would want a static array like that. Occasionally those "empty arrays" (there's a specific name for them that I can't think of right now) are useful at the end of a struct like this:

struct MyDiskObject {
    int numRecords;
    float records[];
};

where MyDiskObject is read off disk (or from the network or whatever), and you know a bunch of floats immediately follow it, so indexing records is indexing into something you know is valid. But that's the only case I know of where empty arrays are useful.

Edited by Samith

Share this post


Link to post
Share on other sites

If you want that kind of behavior where the size is declared in the cpp, it sounds like you might want a static pointer that gets malloced/new'd somewhere in initialization of the class in the cpp.

Edited by ferrous

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!