Reputation: 35
I'm currently trying to compile a crc calculator I took from github and am having difficulty compiling it on visual studio 2015. I get the error expected constant expression for the line:
char paths[strlen(src) + 1 + strlen(name) + 2 + 1];
Thoughts on how I can resolve the error?
static int create_source(char *src, char *name, FILE **head, FILE **code) {
// for error return
*head = NULL;
*code = NULL;
// create the src directory if it does not exist
int ret = _mkdir(src, 0755);
if (ret && errno != EEXIST)
return 1;
// construct the path for the source files, leaving suff pointing to the
// position for the 'h' or 'c'.
char paths[strlen(src) + 1 + strlen(name) + 2 + 1];
char *suff = stpcpy(path, src);
*suff++ = '/';
suff = stpcpy(suff, name);
*suff++ = '.';
suff[1] = 0;
// create header file
*suff = 'h';
*head = fopen(path, "wx");
if (*head == NULL)
return errno == EEXIST ? 2 : 1;
// create code file
*suff = 'c';
*code = fopen(path, "wx");
if (*code == NULL) {
int err = errno;
fclose(*head);
*head = NULL;
*suff = 'h';
unlink(path);
return err == EEXIST ? 2 : 1;
}
// all good -- return handles for header and code
return 0;
}
Upvotes: 1
Views: 227
Reputation: 12600
As a simple alternative to David's solution, you could also use FILENAME_MAX
...
[...] which expands to an integer constant expression that is the size needed for an array of char large enough to hold the longest file name string that the implementation guarantees can be opened; (§7.21.1, ISO C11)
like this
char paths[FILENAME_MAX];
You might like to check that you don't overflow this size, though.
Upvotes: 0
Reputation: 84521
Your immediate problem is you are attempting to use a VLA (Variable Length Array), introduced into the standard with C99, with a compiler that does not support VLAs. Without VLA support, arrays must be declared with an integer constant (not simply a const int
). As of C11, support for VLAs is optional.
To solve your immediate problem and provide portability, simply allocate storage for paths
instead with malloc
. The free
the memory before you return from your function (either though an error return or on success)
You can do something like:
size_t pathlen = strlen(src) + 1 + strlen(name) + 2 + 1;
char *paths = malloc (pathlen); /* allocate storage for paths */
if (!paths) { /* validate EVERY allocation */
perror ("malloc-paths");
return 3; /* or however you want to handle the error */
}
char *suff = stpcpy(path, src);
...
*head = fopen(path, "wx");
if (*head == NULL) {
free (path); /* free paths */
return errno == EEXIST ? 2 : 1;
}
...
if (*code == NULL) {
int err = errno;
free (path); /* free paths */
fclose(*head);
*head = NULL;
*suff = 'h';
unlink(path);
return err == EEXIST ? 2 : 1;
}
free (path); /* free paths */
return 0;
There is a small overhead for the allocation and free, but it is negligible in your case where there is a single allocation and single free.
Upvotes: 3