Reputation: 136
I know the problem seems weird but I need to initialize (or convert) a constant string array in C.
The problem is that the string array is initialized dynamically but an API function I'd like to use only accepts constant string arrays.
I know that this works:
const char *const arr[] = { "test" };
But again: Since I don't know how many items the array will have nor I know the content pre runtime, I can't initialize the array that way.
So of course this won't work
const char *const arr[1];
arr[1] = "test"; // won't work
My question is: Is it possible to convert somehow the dynamically string array to a read-only one? Or is there a way to initialize the array dynamically once?
EDIT 1: My exact problem
int len = 8;
const char *names1[8] = {"test0","test1","test2","test3","test4","test5","test6","test7" }; // not what I'm looking for
const char *names2[len];
const char *names3[len];
// nearly what I'm looking for
for(int j=0; j<len; j++) {
names2[j] = "test";
}
// exactly what I'm looking for
for(int j=0; j<len; j++) {
sprintf(names3[j],"%s%d","test",j); // discards 'const' qualifier
}
// ...
Cudd_DumpDot(gbm, 1, ddnodearray, names1, NULL, outfile);
Cudd_DumpDot(gbm, 1, ddnodearray, names2, NULL, outfile);
Cudd_DumpDot(gbm, 1, ddnodearray, names3, NULL, outfile); // won't work
Okay this is my progress so far.
The method with names2
is indeed working but I'd like to use sprintf
(as shown with names3
) since I need to append j
in this case. And this would wound the const
qualifier.
Upvotes: 3
Views: 2095
Reputation: 7287
Technically there is nothing stopping you from casting the pointer to (char *
) and then setting the elements with memset
or alike.
However this invokes undefined behaviour since the compiler can put it into read-only marked memory.
Excerpt from an answer on another SO question:
The const qualifier is an instruction to the compiler to reject code that attempts to modify that object directly; attempts to modify the object indirectly (as you do in the second code snippet) results in undefined behavior, meaning any result is possible.
There is no way (without invoking UB) to change a constant after its initialisation - so don't do that.
UPDATE As @chux pointed out in the comments it is indeed possible to dynamically initialize local variables.
Upvotes: 3
Reputation: 154055
Initialize a constant string array dynamically
Within a function, there are various ways to initialize a const
string array at run-time.
// example
const char *s[2] = { (char [3]){ rand(), 0, 0},(char [3]){ rand(), 0, 0} };
Yet it appears OP needs only something like that.
Form the various strings, each in valid memory.
// Exmaple
#define SZ (4 + 11 + 1)
char buf[len][SZ];
for(int j=0; j<len; j++) {
sprintf(buf[j],"%s%d","test",j);
}
Form an array of const char *
const char *names[len];
for(int j=0; j<len; j++) {
names[len] = buf[len];
}
Call Cudd_DumpBlifBody()
. The char const *const *
parameters can be called with type char const *const *
or char const **
#include <stdio.h>
#include <stdlib.h>
typedef void DdManager;
typedef void DdNode;
int Cudd_DumpBlifBody(DdManager *dd, int n, DdNode **f,
char const *const *inames,
char const *const *onames, FILE *fp, int mv) {
return 0;
}
#define SZ (4 + 11 + 1)
int sw(int len) {
char buf[len][SZ];
const char *names[len];
for(int j=0; j<len; j++) {
sprintf(buf[j],"%s%d","test",j);
names[len] = buf[len];
}
char const *const *inames = names;
char const *const *onames = names;
return Cudd_DumpBlifBody (NULL, 0, NULL, inames, onames, NULL, 0);
}
Local objects like char buf[len][SZ];
could easlily get too large for local storage. Consider *alloc()
if unsure or if len
could be large.
Upvotes: 1
Reputation:
an API function I'd like to use only accepts constant string arrays.
That's no reason to pass an array of constant pointers ... the conversion to const
(in this case constant array elements) is allowed (and even implicit), so the following (nonsensical) code compiles just fine:
const char *test(const char *const *foo)
{
return foo[0];
}
int main(void)
{
const char *arr[10];
arr[0] = "Foobar";
const char *x = test(arr);
return (int) *x;
}
Upvotes: 2