In a standards compliant environment, you can define a variable-length array (VLA) by using non-constant expressions in the variable definition. This expression must evaluate to a value greater than zero.
VLAs cannot be initialized in their definitions, and must be initialized "by hand" after they are defined.
memset
can be used to quickly fill a number of bytes with some constant byte. This can be useful for initializing all bytes to zero, which for integers is guaranteed to represent zero1.
Otherwise, use basic loops to initialize.
Because VLAs exist on the stack, care must be taken to ensure they do no exceed the maximum stack size on your platform.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void die(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int valid(size_t n) {
/* arbitrary upper bounds, platform dependent */
return n > 0 && n < 512;
}
int main(void) {
size_t x, y;
printf("Enter X dimension: ");
if (1 != scanf("%zu", &x))
die("Could not read X dimension.");
printf("Enter Y dimension: ");
if (1 != scanf("%zu", &y))
die("Could not read Y dimension");
if (!valid(x) || !valid(y))
die("Invalid dimensions.");
int data[x][y];
printf("[data] size in bytes is: %zu\n", sizeof data);
/* All bytes zero */
memset(data, 0, sizeof data);
/* Or, a particular value */
for (size_t i = 0; i < x; i++)
for (size_t j = 0; j < y; j++)
data[i][j] = 42;
}
Some additional notes:
Formally, the proper type for dealing with memory sizes is size_t
. Its format specifier is "%zu"
.
The return value of scanf
should always be checked to ensure the expected number of conversions took place.
The format string " %c"
(note the leading space) can be used to read a single character while ignoring leading white space. This is useful because previous calls to scanf
may leave characters such as the newline (\n
) in the input buffer.
From various comments we can see one of your issues is that you are using the MSVC C compiler. This is an ancient, non-standards compliant compiler that has very poor support for C99 features, including VLAs.
In this case, you may want to use dynamic memory allocation to create your array. You'll need similar validation, but generally speaking heap memory is more vast.
Every call to malloc
needs a mirrored called to free
when you are done using the memory, and care must be taken in cleaning up memory in the event of a partial failure.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void die(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
int valid(size_t n) {
return n > 0 && n < 2048;
}
int main(void) {
size_t x, y;
printf("Enter X dimension: ");
if (1 != scanf("%zu", &x))
die("Could not read X dimension.");
printf("Enter Y dimension: ");
if (1 != scanf("%zu", &y))
die("Could not read Y dimension");
if (!valid(x) || !valid(y))
die("Invalid dimensions.");
int **data = malloc(sizeof *data * x);
if (data == NULL)
die("Could not allocate memory.");
for (size_t i = 0; i < x; i++) {
if (!(data[i] = malloc(sizeof *data[i] * y))) {
for (size_t j = 0; j < i; j++)
free(data[j]);
free(data);
die("Failed to allocate memory.");
}
}
printf("[data] size in bytes is: %zu\n", sizeof (int) * x * y);
for (size_t i = 0; i < x; i++)
free(data[i]);
free(data);
}
1 All bits zero is not a guaranteed representation of zero for all types, e.g., floating point numbers.