3

In C (NOT C++), I am trying to create two string tables that contain the same values, but have the values sorted in two different ways. And I don't want the strings to be duplicated in memory.

Basically, I want to do the following. Except according to gcc, it fails because "initializer element is not constant" in the second array initialization. Is there some way around this problem? Preferably without saying "oh, well the compiler should optimize it to do what you want"?

static const char * monthNames[] = {
  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};


/******** 
 * Month table sorted for O(log N) string lookup
 */
static const char * monthSortedKeys[]= {
  monthNames[3],          /* Apr */
  monthNames[7],          /* Aug */
  monthNames[11],         /* Dec */
  monthNames[1],          /* Feb */
  monthNames[0],          /* Jan */
  monthNames[6],          /* Jul */
  monthNames[5],          /* Jun */
  monthNames[2],          /* Mar */
  monthNames[4],          /* May */
  monthNames[10],         /* Nov */
  monthNames[9],          /* Oct */
  monthNames[8]           /* Sep */
};

Clarification: I know how to do this with a loop. I'm trying to figure out how to do it at compile time.

Another Update: I just compiled this as C++ (g++) and it works. But again, I'm looking for the C answer.

2
  • Oh, well the compiler should optimize it to do what you want Commented Nov 11, 2011 at 22:00
  • @K-ballo +1 for humor. And I just tested that theory and it does. And I thought it would. But I was hoping for a way to do it explicitly. On a system with only 256KB of ROM (and less RAM), it's nice to know at a glance that your code is not wasting ROM. Commented Nov 11, 2011 at 22:11

2 Answers 2

5

Example code snippet:

static const char
    JAN[] = "Jan",
    FEB[] = "Feb",
    // ...
    DEC[] = "Dec";

static const char *const monthNames[] = {
  JAN, FEB, /* ... */ DEC
};

static const char *const monthSortedKeys[]= {
    /* APR, ... */ DEC, /* ... */ FEB, JAN /* ... SEP */
};
Sign up to request clarification or add additional context in comments.

1 Comment

I need something like that, but I'm passing the string array as argv to a main (used to be main, now it's renamed) function. The const qualifier will prevent the match in the function prototype.
1

This seems to work for me:

static const char monthNames[][4] = ...

I would have thought that declaring the pointers as constants would have helped, but as others have pointed out, it doesn't.

5 Comments

nice one - didn't think of that; my solution might still be more readable, though...
Close.... except that it breaks sizeof(). That's one subtle difference between static const char * array[] and static const char array[][]. The first will cause sizeof() to return the number of pointers in the array. The second will cause sizeof() to return the size of the 2D array.
as to why this works and not the original code: in Brian's code, monthNames[3] needs to actually evalute *(monthNames + 3) - ie read a value from memory - whereas in your code, it is equivalent to (char *)(monthNames + 3) - no memory access necessary, just some pointer arithmetics
@Brian: shouldn't really matter - the following will still hold: sizeof monthNames / sizeof *monthNames == sizeof monthSortedKeys / sizeof *monthSortedKeys
@Christoph I suppose that's a good point since I use sizeof() to get the number of strings in the table. However, I think your answer is probably generally preferable since it can be extended to work for varied string lengths. The only down side is that it's a little more verbose than it needs to be.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.