Using non-const for array size

S

Star

I was surprised this code worked on Sun Solaris and AIX.

#include <stdio.h>
int MAX_SIZE = 10;
static void set_max()
{
printf("Before setting max MAX_SIZE is %d\n",MAX_SIZE);
MAX_SIZE = 20;
printf("After setting max MAX_SIZE is %d\n",MAX_SIZE);
}
static void print_array_size()
{
int arr[MAX_SIZE];
printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));
}
int main()
{
set_max();
print_array_size();
return 0;
}

This printed:

Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?
 
A

Andrew Poelstra

...
int arr[MAX_SIZE];
...

I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

In C99 you can use variable-length arrays. But support is spotty,
and even where they are supported there is no real way to detect
out-of-memory conditions, so most people just avoid them.
 
B

Ben Bacarisse

About: Using non-const for array size
[It helps to have all the information in the message body.]
I was surprised this code worked on Sun Solaris and AIX.

It's a feature from C99 (the current standard) often called variable
length arrays, but technically called "variably modified array types".
#include <stdio.h>
int MAX_SIZE = 10;
static void set_max()
{
printf("Before setting max MAX_SIZE is %d\n",MAX_SIZE);
MAX_SIZE = 20;
printf("After setting max MAX_SIZE is %d\n",MAX_SIZE);
}
static void print_array_size()
{
int arr[MAX_SIZE];
printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));

sizeof yields a value of type size_t, not int. You can print a size_t
using the %zu format. Alternatively you can cast the result before
printing, but if you are using C99 features anyway, just use %zu.
}
int main()
{
set_max();
print_array_size();
return 0;
}

It's better to void in the ()s of a function definition
when the function takes no arguments.
This printed:

Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

It should have ended up with 80 not 8. Did you just loose a 0?
I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

Using C99 features limits (to some extent) the potability of your code
since not all compilers implement the same set of C99 features. I
understand that Microsoft compilers don't understand these VLAs for
example. If you are sticking to Unix-like systems, I don't think
you'll have much trouble.

Of course, the whole feature has a problem: you can't tell if the
allocation succeeded. This is true of any automatic data in a
function, but is often more of a problem with large arrays.
 
S

Star

About: Using non-const for array size
[It helps to have all the information in the message body.]
I was surprised this code worked on Sun Solaris and AIX.

It's a feature from C99 (the current standard) often called variable
length arrays, but technically called "variably modified array types".
#include <stdio.h>
int MAX_SIZE = 10;
static void set_max()
{
    printf("Before setting max MAX_SIZE is %d\n",MAX_SIZE);
    MAX_SIZE = 20;
    printf("After setting max MAX_SIZE is %d\n",MAX_SIZE);
}
static void print_array_size()
{
    int arr[MAX_SIZE];
    printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));

sizeof yields a value of type size_t, not int.  You can print a size_t
using the %zu format.  Alternatively you can cast the result before
printing, but if you are using C99 features anyway, just use %zu.
}
int main()
{
    set_max();
    print_array_size();
    return 0;
}

It's better to void in the ()s of a function definition
when the function takes no arguments.
This printed:
Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

It should have ended up with 80 not 8.  Did you just loose a 0?
I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

Using C99 features limits (to some extent) the potability of your code
since not all compilers implement the same set of C99 features.  I
understand that Microsoft compilers don't understand these VLAs for
example.  If you are sticking to Unix-like systems, I don't think
you'll have much trouble.

Of course, the whole feature has a problem: you can't tell if the
allocation succeeded.  This is true of any automatic data in a
function, but is often more of a problem with large arrays.

Thanks Ben. Yes, I missed a zero. It printed:
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 80
 
E

Eric Sosman

[...]
int MAX_SIZE = 10;
[... later changed to 20 ...]
static void print_array_size()
{
int arr[MAX_SIZE];
printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));
}
[...]
This printed:

Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

Is anyone else surprised at the final line of output?
Yes, it's possible that printing a size_t value with "%d"
could do odd things, but this isn't one of the oddities I'd
have expected. Thoughts?
 
K

Keith Thompson

Star said:
I was surprised this code worked on Sun Solaris and AIX.

#include <stdio.h>
int MAX_SIZE = 10; [...]
int arr[MAX_SIZE]; [...]

I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

In addition to what you've already been told about VLAs
(variable-length arrrays), you should be aware that "const" and
"constant" are very different things. "const" doesn't really mean
"constant"; it means "read-only". For example, if you had written:

const int MAX_SIZE = 10;
int arr[MAX_SIZE];

then arr would still be a VLA, and even in C99 you couldn't legally
write:

switch (...) {
case MAX_SIZE:
...

<OT>C++ would treat MAX_SIZE as a constant.</OT>
 
E

Eric Sosman

[...]
int MAX_SIZE = 10;
[... later changed to 20 ...]
static void print_array_size()
{
int arr[MAX_SIZE];
printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));
}
[...]
This printed:

Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

Is anyone else surprised at the final line of output?
Yes, it's possible that printing a size_t value with "%d"
could do odd things, but this isn't one of the oddities I'd
have expected. Thoughts?

Never mind: In a follow-up, the O.P. said he'd trimmed a
trailing zero, and the output was 80, not 8. (I was starting
to imagine compiler problems causing sizeof(arr) to report the
size of a 64-bit behind-the-scenes pointer instead of the size
of the VLA -- but it's nothing so interesting.)
 
S

Seebs

I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

Congratulations, you have finally proved that two wrongs make a right!

1. In C, "const" doesn't have any effect related to this in any way. In
C++, "const int x = 20" means that x can then be used as an array size,
because the compiler knows it's 20. In C, this doesn't have any effect.
2. In C99, and GNU C, and some other variants, array sizes don't have
to be constant at all.

So the fact is, you're wrong about expecting const to be required, and
also about expecting const to do anything, but it does turn out that the
code should work in C99 and GNU C compilers. I assume someone's still
maintaining a compiler without this feature out of sheer spite, but I
haven't had cause to deal with one in a decade or so.

-s
 
B

Barry Schwarz

About: Using non-const for array size
[It helps to have all the information in the message body.]
I was surprised this code worked on Sun Solaris and AIX.

It's a feature from C99 (the current standard) often called variable
length arrays, but technically called "variably modified array types".
#include <stdio.h>
int MAX_SIZE = 10;
static void set_max()
{
    printf("Before setting max MAX_SIZE is %d\n",MAX_SIZE);
    MAX_SIZE = 20;
    printf("After setting max MAX_SIZE is %d\n",MAX_SIZE);
}
static void print_array_size()
{
    int arr[MAX_SIZE];
    printf("MAX_SIZE is %d sizeof(int arr[MAX_SIZE]) is %d
\n",MAX_SIZE,sizeof(arr));

sizeof yields a value of type size_t, not int.  You can print a size_t
using the %zu format.  Alternatively you can cast the result before
printing, but if you are using C99 features anyway, just use %zu.
}
int main()
{
    set_max();
    print_array_size();
    return 0;
}

It's better to void in the ()s of a function definition
when the function takes no arguments.
This printed:
Before setting max MAX_SIZE is 10
After setting max MAX_SIZE is 20
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 8

It should have ended up with 80 not 8.  Did you just loose a 0?
I thought it would give a compile error since MAX_SIZE is not a const
int type. So it fine not to use const for array lengths ? Appreciate
your feedback ?

Using C99 features limits (to some extent) the potability of your code
since not all compilers implement the same set of C99 features.  I
understand that Microsoft compilers don't understand these VLAs for
example.  If you are sticking to Unix-like systems, I don't think
you'll have much trouble.

Of course, the whole feature has a problem: you can't tell if the
allocation succeeded.  This is true of any automatic data in a
function, but is often more of a problem with large arrays.

Thanks Ben. Yes, I missed a zero. It printed:
MAX_SIZE is 20 sizeof(int arr[MAX_SIZE]) is 80

size_t is an unsigned type. Your call to printf invokes undefined
behavior. While entirely possible, I have a hard time believing a
current C99 compiler with sizeof(int) = 4 has size_t as a typedef for
unsigned int (but that is just my problem). Chances are you are on a
little endian system so the undefined behavior fooled you by doing
what you expected.
 
E

Eric Sosman

[... printf-ing size_t with "%d" ...]
size_t is an unsigned type. Your call to printf invokes undefined
behavior. While entirely possible, I have a hard time believing a
current C99 compiler with sizeof(int) = 4 has size_t as a typedef for
unsigned int (but that is just my problem). Chances are you are on a
little endian system so the undefined behavior fooled you by doing
what you expected.

The erroneous code will "work" on plenty of big-endian
systems, too. The O.P. mentioned Solaris; the code would
"work" on SPARC, and maybe also on x86/x64. (He also mentioned
AIX; I don't know the situation there.)

In any case, the fact that the code "works" is not evidence
of endianness.
 
K

Keith Thompson

Barry Schwarz said:
size_t is an unsigned type. Your call to printf invokes undefined
behavior. While entirely possible, I have a hard time believing a
current C99 compiler with sizeof(int) = 4 has size_t as a typedef for
unsigned int (but that is just my problem). Chances are you are on a
little endian system so the undefined behavior fooled you by doing
what you expected.

Why is that hard to believe? On a 32-bit system, why shouldn't size_t
be a typedef for unsigned int? (In fact, that's exactly what it is
two 32-bit systems I just tried.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,778
Messages
2,569,605
Members
45,237
Latest member
AvivMNS

Latest Threads

Top