# C/C++ question, const versus #define for defining array.

1. Sep 23, 2011

### uart

I know that it's often considered better practice to use C's "typed constants" instead of "#define" as it may offer better error/type checking. I'm wondering however what happens if a const is used to declare the size of an array. For example consider the two possible methods below.

Code (Text):
#define ListSize 80
typdef int List[ListSize];

Code (Text):
const int ListSize = 80;
typdef int List[ListSize];
The latter doesn't compile in standard C as it doesn't seem to recognize ListSize as a compile-time constant. It does however compile ok in c++, but I'm wondering if it does actually allocate the size specified (80 in this case) right there at compile time?

Does anyone know the nitty gritty on this?

Thanks.

Last edited: Sep 23, 2011
2. Sep 23, 2011

### phinds

Don't see how it could make any difference, since at compile time (ASSUMING that the compiler implementation retains the constant in time to use it in the same compiler pass) the statement

typdef int List[ListSize];

is the same (in your example) as

typedef int List[80];

As to your specific question, "compile time" is a bit more complicated than you seem to imply but in any case, NOTHING is actually allocated at compile time. It's put into an object file and the object file is loaded at load time and THEN some things get allocated.

If your questions is does the memory get allocate at load time or at run time, then it may depend on where the statement is (main module vs sub-module) but I think in general it gets allocated at run time as part of memory management.

3. Sep 23, 2011

### uart

Sorry I worded that badly. Yes I know that the memory doesn't get allocated at compile time, what I meant is whether it would be literally using "ListSize" as a constant (80 in this case) at compile time or if it was producing code to dynamically allocate the array based on an inquiry to the value of "ListSize" at load/run time.

It didn't really think it was the latter, but I'm confused about why the code with the "const int ..." statement doesn't compile in standard C (it does however compile in c++). The error it gives in standard C is "variable-sized type declared outside of any function".

4. Sep 23, 2011

### rcgldr

My guess is in the case of the C++ compiler, in the compile time symbol table, it's treats the const int ListSize also as a define, while the C compiler doesn't treat it as a define.

In terms of allocation at compile time versus run time, it depends on what the operating system's loader is capable of when loading a program. For most operating systems, a typical program includes these sections: code, data, stack, with data separated into initialized data, zeroed data (statics in c), and unitialized data. The loader may be unaware of zeroed data, but the program will contain initialization code to zero out that part of the data section. The zeroed and unitialized data just have size information in a typcial program image (I think a MSDOS type .com program contains everything in one large chunk).

5. Sep 23, 2011

### uart

Here's an interesting little twist to this. The error message "variable-sized type declared outside of any function" seems to imply that it wouldn't be a problem if it was inside a function, but as you know error messages are not always that descriptive.

Well I decided to just test this anyway, and used the "const" to define an array inside the main program and it did actually work correctly.

So in the program preamble (before the code main or any other functions) the code
Code (Text):
const int ListSize = 80;
typdef int List[ListSize];
wont compile in standard C.

However if I scrap the typedef (but leave the const defined there) and then place the following in the main program,
Code (Text):

const int ListSize = 80;
...
int main(void) {
int myList[ListSize];
...

then curiously it does compile without any issue.

I think I'll just have to put this down to a quirk in C and move on.

6. Sep 23, 2011

### phinds

actually, "quirk" may not be quite right in this case as I think it's a specific design decision to require that typedefs NOT have external references. That is, a typedeff has to be self-contained because it is going to just REPLACE code elsewhere and allowing it to have external reference opens up a can of worms for OTHER errors. A #define is NOT taken as an external reference because it is immediately replace by the compiler as the typedef is being stored away to be used to replace code later.

7. Sep 23, 2011

### Hurkyl

Staff Emeritus
Try making it static. Also, are you compiling to the C99 standard, or the older one?

8. Sep 23, 2011

### uart

I tried making it static but it didn't change the error.
Unfortunately I don't know if this is C99 or older. I'm using Dev-C++ and the version of "gcc" in its bin directory is 3.4.2

This is not terribly important, I really don't have a problem using #define here. I was just helping my nephew with a trivial C program, basically showing him how to tidy it up by defining types and constant etc. I noticed that he's supposed to be writing it in standard C only but he had the file named $#.cpp. I renamed it to$#.c and the compiler immediately came up with a few errors where some c++ only code had been used. These were all easily fixed but the one with the const just bothered me a bit as to why it had that behavior.

BTW. I've just found a good link on stackoverflow where exactly this topic has been discussed. They seem to have come to the same conclusion as here.

To the question
I thought this response was good and very thorough.
Ref : http://stackoverflow.com/questions/1674032/static-const-vs-define-in-c

Last edited: Sep 23, 2011
9. Sep 23, 2011

### D H

Staff Emeritus
That is an old version of gcc. You can get something a bit more modern that is still free.

Anyhow, the problem here is that 'const' doesn't quite mean 'const' in C. So as far as C is concerned, this is a variable-length array, and variable length arrays are only valid as local variables (i.e., some function's internal variable). You can't use variable length arrays at file scope or as an element of a structure.

That answer provides one key alternative to a const int or a #defined value: Use an enum value to size your arrays. This is a compile-time constant to both C and C++.

As far as sizing an array, a "static const int" is not the way to go in C++ unless the array itself has static scope. If the array has extern scope, the array size had also better have extern scope.

Last edited: Sep 23, 2011
10. Sep 23, 2011

### Hurkyl

Staff Emeritus
Eh?

Oh, I think I have an idea what you might mean, but it could only be a worry in certain cases. e.g. the following would be just fine, even preferred:

Code (Text):
static const size_t my_array_size = 32;
extern int my_array[my_array_size];

// mysource.cc

int my_array[my_array_size];

11. Sep 23, 2011

### Hurkyl

Staff Emeritus
Oh well. Alas I don't have a convenient C compiler on this computer so I couldn't check myself.

I hadn't realized that particular difference between enum and static const int; interesting.