In main:
char *myData[500][9]; //dynamic rows??
char **tableData[500]={NULL}; //dynamic rows??
int r;
newCallBack(db, &myData, &tableData, &r);
and passing into function by:
void newCallBack(sqlite3 *db, char** mdat, char*** tdat, int* r )
{
Doesn't seem to like this? Any suggestions? Lots of examples online when you don't know the size, trying them out right now....
Thanks.
If you were to rewrite this as such:
#define NUM_ROWS 500;
#define NUM_COLS 9;
char **myData = NULL;
char *tableData = NULL;
int i;
int r;
myData = malloc(sizeof(char *) * NUM_ROWS);
if (!myData)
return; /*bad return from malloc*/
tableData = malloc(sizeof(char) * NUM_ROWS);
if (!tableData)
return; /*bad return from malloc*/
for (i = 0; i < NUM_ROWS; i++)
{
myData[i] = malloc(sizeof(char) * NUM_COLS);
if (!myData[i])
return; /*bad return from malloc*/
}
You would then call newCallBack() like this if you just wanted access to the data (myData, tableData, and r):
/*prototype*/
void newCallBack(sqlite3 *db, char** mdat, char* tdat, int r);
/*call*/
newCallBack(db, myData, tableData, r);
Or this if you want to be able to modify what the vars myData and tableData point to and the value of r:
/*prototype*/
void newCallBack(sqlite3 *db, char ***mdat, char **tdat, int *r);
/*call*/
newCallBack(db, &myData, &tableData, &r);
First of all, the problem with myData is that it's the wrong type. char* [][] would require a prototype char*** (a two-dimensional array of strings) in the function you're calling. The function wants a list of strings, which is char* [], or alternatively char[][], if you don't mind limiting the size of the strings.
To get fully dynamic array sizes you'll have to manually allocate (and release!) memory with malloc() and free(), and change the types of your variables to char **myData and char ***tableData.
Related
I have a program in C, in which I initialize multiple number of arrays each with a bunch of lines. However, i'd like to avoid that since it increases the length of my main function. For example I have this;
int * pickup_Ind;
double *pickup_Val;
pickup_Ind = (int *) malloc(sizeof(int) * (size1));
pickup_Val = (double *) malloc(sizeof(double) * (size1));
int * lInd;
double *lVal;
lInd = (int *) malloc(sizeof(int) * size2);
lVal = (double *) malloc(sizeof(double) * size2);
int * simul_Ind;
double *simul_Val;
simul_Ind = (int *) malloc(sizeof(int) * (size3));
simul_Val = (double *) malloc(sizeof(double) * (size3));
I know I can reduce the number of lines by for example writing as:
int * pickup_Ind = (int *) malloc(sizeof(int) * (size1));
But still i will need to do this for every array. How to write this in a compact form with a function (which i will store in a header file), and then call this function from main. Not to mention i do not want to declare them as global variables, but to be able to use them in main. I tried the function below.
void initialize_bounds(int *arr1,int size1)
{
arr1= (int *) malloc(sizeof(int) * (size1));
for(int i=0;i<size1;i++)
arr1[i]=i;
}
But if i call this function via the following in main, i get error "Varuable test being used without initialized"
int* test;
initialize_bounds(test);
So to sum up, if i could write something like this, my problem is solved:
int *pickup_Ind,*pickup_Val,*lind,*lval;
int size1,size2;
initalize_bounds(pickup_Ind,pickup_Val,size1,size2);
You could write a function
void initialize_bounds(int **ind, double **val, int size) {
*ind = malloc(sizeof (**ind)*size);
for (int i = 0; i < size; i++) {
(*ind)[i] = i;
}
*val = malloc(sizeof (**val)*size);
}
and call it like
int * pickup_Ind;
double *pickup_Val;
initialize_bounds(&pickup_Ind, &pickup_Val, size1);
to initialize both arrays in one line. You still have to place one call to it per array-pair, however.
In the C language, arguments are passed to functions by value - so, actually, a copy is made and the original variable (in the calling code) cannot be changed. So, if you want a function to modify (say) an int argument, you pass it a pointer to that int.
Likewise, if you want a function to modify a pointer, you have to pass a pointer to that pointer.
So, in the case of the initialize_bounds function you have shown, you would need this:
void initialize_bounds(int** arr1,int size1) // 1st arg is a pointer to the pointer!
{
*arr1 = (int *) malloc(sizeof(int) * (size1)); // De-reference our `arr1` pointer
for(int i=0;i<size1;i++)
(*arr1)[i]=i;
}
Then, you can use this to initialize a pointer in your main function with a call like this:
int* test;
initialize_bounds(&test); // We need to pass the ADDRESS of the pointer we want to modify!
You can write a function that returns a freshly allocated and initialized array.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
/* Header file */
int* AllocateArray(size_t size);
void DeallocateArray(int *array);
int main(void) {
const size_t size = 10;
int *const array = AllocateArray(size);
for (size_t i = 0; i < size; ++i) {
printf("%d ", array[i]);
}
printf("\n");
DeallocateArray(array);
return 0;
}
/* Implementation */
int* AllocateArray(size_t size) {
int *const array = malloc(size * sizeof(int));
if (array == NULL) {
// Allocation failed, handle it...
}
for (size_t i = 0; i < size; ++i) {
array[i] = i;
}
return array;
}
void DeallocateArray(int *array) {
if (array == NULL) {
return;
}
free(array);
}
I'd use something higher level, e.g. stretchy buffers. See this video for a live coding session that implements those - props to Per Vognsen for making this code, and for placing into public domain (i.e. completely free to use for any purpose, but I'm not a lawyer, so take anything I say with caution :).
You'd want to include bitwise/ion/common.c in your source file, and then the array allocation becomes simple. Stretchy buffers are perhaps the closest you get to the convenience of C++'s std::vector in C. They offer an API that doesn't feel like a C++ API transcribed in C - it is at the correct level, and lets you use plain pointers in a very sensible way (e.g. a buf_len of a NULL pointer is zero, not a crash, buf_push(mybuf, element) appends an element to the array and extends it if necessary, etc.
#include <assert.h>
#include <string.h>
#include <stdlib.h>
// note that common.c includes nothing, so you have to set it up
#include "common.c"
#define buf_resize(b, n) ((n) <= buf_len(b) ? (b) : (((b) = buf__grow((b), (n), sizeof(*(b)), 0)), ((b) ? buf__hdr((b))->len = (n) : 0), (b)))
typedef struct {
int * pickup_Ind;
double *pickup_Val;
int * lInd;
double *lVal;
int * simul_Ind;
double *simul_Val;
} Data;
enum {
size1 = ...,
size2 = ...,
size3 = ...
}
Data make_Data(void) {
Data d;
memset(&d, 0, sizeof(d));
assert(buf_len(d->pickup_Ind) == 0);
buf_resize(d.pickup_Ind, size1);
buf_resize(d.pickup_Val, size1);
buf_resize(d.lInd, size2);
buf_resize(d.lVal, size2);
buf_resize(d.simul_Ind, size3);
buf_resize(d.simul_Val, size3);
}
int main(int argc, char **argv) {
Data d = make_Data();
assert(buf_len(d.pickup_Ind) == size1);
d.pickup_Ind[0] = 10;
assert(buf_len(d.pickup_Ind) == size1);
buf_push(d.pickup_Ind, 11);
assert(buf_len(d.pickup_Ind) == size1 + 1);
}
If you're building up the arrays by adding elements to them one-by-one, it'll make sense to reserve the capacity for the expected size of the array via buf_fit (it only reserves the memory but the buffer retains its length (e.g. zero)). The capacity reservation is entirely optional, though. It's there to prevent reallocation of the arrays while you add elements to them.
Thus:
Data make_Data(void) {
Data d;
memset(&d, 0, sizeof(d));
assert(buf_len(d->pickup_Ind) == 0);
buf_fit(d.pickup_Ind, size1);
buf_fit(d.pickup_Val, size1);
buf_fit(d.lInd, size2);
buf_fit(d.lVal, size2);
buf_fit(d.simul_Ind, size3);
buf_fit(d.simul_Val, size3);
}
int main(int argc, char **argv) {
Data d = make_Data();
assert(buf_len(d.pickup_Ind) == 0); // zero length: no data in the array (yet!)
assert(buf_cap(d.pickup_Ind) >= size1); // but it has the capacity we need
buf_push(d.pickup_Ind, 10);
buf_push(d.pickup_Ind, 11);
assert(buf_len(d.pickup_ind) == 2);
}
If you'll want to use stretchy buffers in multiple source files, you'll run afoul of the one declaration rule (ODR). Thus, you'll need to factor out macro definitions and function declarations out of common.c and into common.h.
If the Data is only allocated once, there's no need to free it prior to exiting the program: the operating system already does it for you. Otherwise, you may wish to add a function to do this job:
void free_Data(Data *d) {
buf_free(d.pickup_Ind);
buf_free(d.pickup_Val);
buf_free(d.lInd);
buf_free(d.lVal);
buf_free(d.simul_Ind);
buf_free(d.simul_Val);
assert(buf_len(d.pickup_Ind) == 0);
}
I am working on a sqlite-.dll for educational purpose.
I am trying to dynamically add a row in my 2 dimensional array for each time the callback function is called with a new row from the database. (e.g. SELECT * FROM CUSTOMER).
The data stored in this array should then be returned as a C-Interface.
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
char **a = 0;
/*Some sqlite stuff*/
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a;
}
With the callback function:
static int callback(void *data, int argc, char **argv, char **azColName)
{
char **old = (char **)data;
int num_rows = sizeof(old) / sizeof(old[0]);
int num_cols = sizeof(old[0]) / sizeof(old[0][0]);
old = (char **)realloc(old, (num_rows + 1) * sizeof(char *));
for (int i = 0; i < (num_rows + 1); i++)
old[i] = (char *)realloc(old[i], argc * sizeof(char *));
/*I am trying to create a 2 dim array that looks like a table,
so the column names are in the first row,
then the data from the table is stored in each row*/
for (int i = 0; i < argc; i++)
{
if (num_rows == 1)
old[0][i] = *azColName[i];
old[num_rows][i] = *argv[i];
}
data = old;
return 0;
}
When inserting data to the database, everything works fine. But when I try to retrieve data, I get read access violation.
Now my question, am I on the right way with my approach or do I miss some important requirements for my intention?
In your sql_execQuery(), you declare a as a char **, and you pass its address, &a, as the fourth argument of sqlite3_exec(). That argument therefore has type char ***, and it points to a location somewhere in the program's stack. There's nothing inherently wrong with that.
But then we get to callback(), which has serious problems, principal among them:
It treats the data pointer as if it were of type char **, instead of the correct type, char ***. If that were your only problem, you could fix it like this:
char **old = *(char ***)data;
// ...
*(char ***)data = old;
It tries to compute the dimensions of the allocated space via the sizeof operator, as would be reasonable if old were, in fact, a 2D array, but it is not an array at all. It is a pointer to pointer to char, so sizeof(old) is the size of a pointer (to pointer to char), sizeof(old[0]) is the size of a pointer (to char) and sizeof(old[0][0]) is the size of a char. This does not tell you anything about how much space has been allocated.
After allocating memory for old, it dereferences the parts of the allocated memory without initializing them, by passing them to realloc(). Generally, all but one of these will have been initialized, but the one uninitialized one causes realloc() to exhibit undefined behavior.
You fail to check for allocation errors.
It looks like you need a more complex data structure to be passed through to your callback, so that you can track the allocated dimensions. Something like this, for example:
struct mytable {
char **data;
size_t dim;
};
SQLCONTROL_API char** sql_execQuery(char *dbName, char *sqlStatement)
{
struct mytable a = { NULL, 0 };
// ...
int rc = sqlite3_exec(db, sqlStatement, callback, &a, &zErrMsg);
return a.data;
}
static int callback(void *data, int argc, char **argv, char **azColName)
{
struct mytable *old = data;
char **temp;
old->dim++;
temp = realloc(old->data, old->dim * sizeof(*old->data));
if (temp) {
old->data = temp;
old->data[old->dim - 1] = NULL;
} else {
// handle allocation error ...
}
for (int i = 0; i < old->dim; i++) {
char *temp2 = realloc(old->data[i], argc * sizeof(*old->data[i]));
if (temp2) {
old->data[i] = temp2;
old->data[i][argc - 1] = NULL;
} else {
// handle allocation error ...
}
}
// ... other stuff ...
// no need for anything like data = old
return 0;
}
I have been searching for a solution but can't seem to find one similar to mine. Am trying to sort
a 2D char * array by a certain column.
char *objs[50][3];
/***** within a loop to populate with values *****/
objs[count][0]=obj->level; //this is a number to be sorted
objs[count][1]=obj->cost; //this is a number
objs[count][2]=obj->short_desc->str; //this is a string
count++;
/***** end loop *********/
qsort(objs, count, sizeof(char *), compare_function); //to sort by obj->level, int values
i deleted my previous solution because it was showing all kinds
of weird numbers or not even sorting. i am not very experienced with
C, and would greatly appreciate help on how to do this.
thank you in advance.
When sorting implicit structs in "C" defined by 2d arrays, where each row corresponds to a single object, I find it useful to use qsort_s() because it allows me to pass in more information about the the array entries to be sorted into the comparison function.
Thus the following accepts a 2d array of strings with nRows rows and nColumns columns and sorts on a column specified by sortColumnIndex. The extra context pointer provided to qsort_s() communicates the sort index down to the sorting method without requiring global variables:
struct sort_on_index_context
{
size_t nRows;
size_t nColumns;
size_t sortColumnIndex;
};
static int compare(void *p_vcontext, const void *ventry1, const void *ventry2)
{
struct sort_on_index_context *p_context = (struct sort_on_index_context *)p_vcontext;
char **entry1 = (char **)ventry1;
char *s1 = entry1[p_context->sortColumnIndex];
char **entry2 = (char **)ventry2;
char *s2 = entry2[p_context->sortColumnIndex];
return strcmp(s1, s2);
}
void sort_on_index(char **objs, size_t nRows, size_t nColumns, size_t sortColumnIndex)
{
struct sort_on_index_context context;
if (sortColumnIndex < 0 || sortColumnIndex >= nColumns)
return; /* Print an error or throw an exception! */
context.nColumns = nColumns;
context.sortColumnIndex = sortColumnIndex;
context.nRows = nRows;
qsort_s(objs, nRows, sizeof(char *) * nColumns, compare, (void *)&context);
}
We pass sizeof(char *) * nColumns because we want qsort_s to treat each contiguous group of nColumns char pointers as single blocks to be rearranged in order.
And then you would call it something like this:
char *objs[50][3];
size_t nRows = sizeof(objs)/sizeof(objs[0]);
size_t nColumns = sizeof(objs[0])/sizeof(objs[0][0]);
size_t column_id_to_sort = 1; /* or whatever you want to define as your sort key. */
/* Fill up your "objs" array however you like */
/* Now do the sort: */
sort_on_index(&objs[0][0], nRows, nColumns, column_id_to_sort);
Edit
If qsort_s or some equivalent is not available in your development environment, you may need to communicate the necessary information to your sort function via a static variable, e.g.
static struct sort_on_index_context context;
static int compare(const void *ventry1, const void *ventry2)
{
char **entry1 = (char **)ventry1;
char *s1 = entry1[context.sortColumnIndex];
char **entry2 = (char **)ventry2;
char *s2 = entry1[context.sortColumnIndex];
return strcmp(s1, s2);
}
Update
You can extend the method to supply your own custom comparison method like so:
struct sort_on_index_context_custom
{
size_t nRows;
size_t nColumns;
size_t sortColumnIndex;
int (*comparer)(const char *, const char *);
};
static int compare_custom(void *p_vcontext, const void *ventry1, const void *ventry2)
{
struct sort_on_index_context_custom *p_context = (struct sort_on_index_context_custom *)p_vcontext;
char **entry1 = (char **)ventry1;
char *s1 = entry1[p_context->sortColumnIndex];
char **entry2 = (char **)ventry2;
char *s2 = entry2[p_context->sortColumnIndex];
return p_context->comparer(s1, s2);
}
void sort_on_index_custom(char **objs, size_t nRows, size_t nColumns, size_t sortColumnIndex, int (*comparer)(const char *, const char *))
{
struct sort_on_index_context_custom context;
if (sortColumnIndex < 0 || sortColumnIndex >= nColumns)
return; /* Print an error or throw an exception! */
context.nColumns = nColumns;
context.sortColumnIndex = sortColumnIndex;
context.nRows = nRows;
context.comparer = comparer;
qsort_s(objs, nRows, sizeof(char *) * nColumns, compare_custom, (void *)&context);
}
And then call it like this to sort a given column of strings as integers:
static int integer_compare(const char *s1, const char *s2)
{
int int1 = atoi(s1);
int int2 = atoi(s2);
return int1 - int2;
}
sort_on_index_custom(&objs[0][0], nRows, nColumns, 1, integer_compare);
I messed around with this enough but I really don't get it.
Here is what I want to do: Take a 2D char array as an input in a function, change the values in it and then return another 2D char array.
That's it. Quite simple idea, but ideas do not get to work easily in C.
Any idea to get me started in its simplest form is appreciated. Thanks.
C will not return an array from a function.
You can do several things that might be close enough:
You can package your array in struct and return that. C will return structs from functions just fine. The downside is this can be a lot of memory copying back and forth:
struct arr {
int arr[50][50];
}
struct arr function(struct arr a) {
struct arr result;
/* operate on a.arr[i][j]
storing into result.arr[i][j] */
return result;
}
You can return a pointer to your array. This pointer must point to memory you allocate with malloc(3) for the array. (Or another memory allocation primitive that doesn't allocate memory from the stack.)
int **function(int param[][50]) {
int arr[][50] = malloc(50 * 50 * sizeof int);
/* store into arr[i][j] */
return arr;
}
You can operate on the array pointer passed into your function and modify the input array in place.
void function(int param[][50]) {
/* operate on param[i][j] directly -- destroys input */
}
You can use a parameter as an "output variable" and use that to "return" the new array. This is best if you want the caller to allocate memory or if you want to indicate success or failure:
int output[][50];
int function(int param[][50], int &output[][50]) {
output = malloc(50 * 50 * sizeof int);
/* write into output[i][j] */
return success_or_failure;
}
Or, for the caller to allocate:
int output[50][50];
void function(int param[][50], int output[][50]) {
/* write into output[i][j] */
}
You cannot return an array from a function.
You have several options:
wrap arrays inside structs
struct wraparray {
int array[42][42];
};
struct wraparray foobar(void) {
struct wraparray ret = {0};
return ret;
}
pass the destination array, as a pointer to its first element (and its size), to the function; and change that array
int foobar(int *dst, size_t rows, size_t cols, const int *src) {
size_t len = rows * cols;
while (len--) {
*dst++ = 42 + *src++;
}
return 0; /* ok */
}
// example usage
int x[42][42];
int y[42][42];
foobar(x[0], 42, 42, y[0]);
change the original array
int foobar(int *arr, size_t rows, size_t cols) {
size_t len = rows * cols;
while (len--) *arr++ = 0;
return 0; /* ok */
}
char **foo(const char * const * bar, size_t const *bar_len, size_t len0) {
size_t i;
char** arr = malloc(sizeof(char *) * len0);
for (i = 0; i < len0; ++i) {
arr[i] = malloc(bar_len[i]);
memcpy(arr[i], bar[i], bar_len[i]);
}
/* do something with arr */
return arr;
}
Somewhere else in your code:
char **pp;
size_t *pl;
size_t ppl;
/* Assume pp, pl are valid */
char **pq = foo(pp, pl, ppl);
/* Do something with pq */
/* ... */
/* Cleanup pq */
{
size_t i;
for (i = 0; i < ppl; ++i)
free(pq[i]);
free(pq);
}
Because you're passing by-pointer instead of by-value and you want to write to the input array, you have to make a copy of it.
Here's another example. Tested and works.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void test(char**,unsigned int,unsigned int);
const unsigned int sz_fld = 50 + 1;
const unsigned int sz_ffld = 10;
int main(void) {
char fld[sz_ffld][sz_fld];
for (unsigned char i=0;i<sz_ffld;++i) {
strcpy(fld[i],"");
}
strcpy(fld[0],"one");
strcpy(fld[1],"two");
strcpy(fld[2],"three");
char** pfld = malloc(sz_ffld*sizeof(char*));
for (unsigned int i=0;i<sz_ffld;++i) {
*(pfld+i) = &fld[i][0];
}
test(pfld,sz_ffld,sz_fld);
printf("%s\n",fld[0]);
printf("%s\n",fld[1]);
printf("%s\n",fld[2]);
free(pfld);
return(0);
}
void test(char** fld,unsigned int m,unsigned int n) {
strcpy(*(fld+0),"eleven");
strcpy(*(fld+1),"twelve");
return;
}
Note the following:
For compiling, I am using gcc with the C99 option.
I defined the function to include the two sizes information, but I wrote very basic code and am not actually using the information at all, just the strcpy(), so this certainly is not security-safe code in any way (even though I'm showing the "m" and "n" for such facility). It merely shows a technique for making a static 2D char array, and working with it in a function through the intermediate of an array of pointers to the "strings" of the array.
When you pass a 2D array to a function as a parameter, you need to explicitly tell it the size of the arrays second dimension
void MyFunction(array2d[][20]) { ... }
The following will do what you want. it will print "One" and "Ten". Also note that it is typed to the exact array dimensions of 10 and 8.
char my_array[10][8] =
{
{"One"},
{"Two"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"One"},
{"Nine"},
{"Ten"},
};
void foo ( char (**ret)[10][8] )
{
*ret = my_array;
}
void main()
{
char (*ret)[10][8];
foo(&ret);
printf("%s\r\n", (*ret)[0] )
printf("%s\r\n", (*ret)[9] )
}
The original question was about RETURNING the array, so I'm updating this to show returning a value. You can't "return an array" directly, but you CAN make a typedef of an array and return that...
char my_array[10][8];
typedef char ReturnArray[8];
ReturnArray* foo()
{
return my_array;
}
I want to have a 2d char array, and when I don't use the struct I can loop through the array and print out the strings. However if I assign the 2d char array to a struct member, I cannot access the array, why?
typedef struct {
int num;
char **names;
} test;
test t;
t.num = 2;
char *names[t.num];
char *tmp;
tmp = "test";
names[0] = "something";
strcpy(tmp,names[0]);
strcat(tmp,"appendedtext");
names[1] = tmp;
names[2] = "something else";
t.names = names;
You really should be dynamically allocating your arrays here. There are a lot of problems with the things you are trying to do here.
Your array is initialized to point to memory on the stack.
You are storing pointers to string literals and attempting to modify them.
You are accessing memory beyond the bounds of your array.
And everything in between.
It just so happens I have some utility functions to dynamically allocate 2-dimensional arrays using a single allocation. Feel free to use them in your code.
static size_t getsize(size_t rows, size_t cols, size_t size)
{
size_t ptrsize = rows*sizeof(void *);
if (ptrsize%size != 0)
ptrsize += size - ptrsize%size;
return ptrsize + rows*cols*size;
}
static void init2d(void *mem, size_t rows, size_t cols, size_t size)
{
int i;
char **ptr = mem;
char *base = (char *)(ptr + rows);
size_t rowsize = cols*size;
size_t ptrsize = rows*sizeof(char *);
if (ptrsize%size != 0)
base += size - ptrsize%size;
for (i = 0; i < rows; i++)
ptr[i] = base + i*rowsize;
}
void *malloc2d(size_t rows, size_t cols, size_t size)
{
size_t total_size = getsize(rows, cols, size);
void *mem = malloc(total_size);
init2d(mem, rows, cols, size);
return mem;
}
void *calloc2d(size_t rows, size_t cols, size_t size)
{
size_t total_size = getsize(rows, cols, size);
void *mem = calloc(total_size, 1U);
init2d(mem, rows, cols, size);
return mem;
}
Then your code would look something like this:
#define MAXWIDTH 100
int num = 3;
test t;
t.num = num;
/* dynamically allocate the memory for t.name */
t.names = calloc2d(t.num, MAXWIDTH, sizeof(char));
/* do your thing here */
const char *tmp = "test";
strcpy(t.names[0], tmp);
strcat(t.names[0], "appendtext"); /* just be careful not to go past MAXWIDTH */
strcpy(t.names[1], tmp);
strcpy(t.names[2], "something else");
/* free the memory that was allocated when done */
free(t.names);
t.names = NULL;
shouldn't you alloc memory for your arrays before trying to access them ?
EDIT:
names[2] = "something else" gets you out of index.. you declared only a 2 string array.
Since you said that the memory is declared automatically as a constant, then you should have noticed:
char *tmp;
tmp = "test";
strcpy(tmp, "something"); //something is longer than test