Your programming sample is a very bad example of obfuscated function prone to error and confusion. I suggest you to receed from your intent and consider a more clear alternative, or it will be a nightmare in future revisions.
You are abusing of the sequence of translation pointers at beginning of your structure making appear the last as an array of translations.
Even worst is that there was a perfectly legal mode to achive what you are trying to do. Consider:
typedef struct
{
const char* Translations[LanguageId_Invalid];
int id;
}Translation;
No more union, a simple structure with an array of translations as first field.
Now for the sake of clarification of the C concepts let analyze your software.
In the union you are declaring:
const char** Heap;
That is a variable holding the address of a memory location where there is an array of pointers to char. Read it carefully!
When you try to access data with:
return( *(oneLine.Heap + _currentLanguageId));
the compiler get the address pointed by Heap as the address of the array of char pointers, but it is the address of first string, get the first 4 bytes in that location and treat them as the address of the string. Then program crashes...
In plane words
you're telling that Heap is the address of the array, but it is the array itself.
You must tell to the compiler that at Heap there is the array of pointers, your declaration must be:
const char* Heap[];
More, using loops on repetitive tasks as translation is not the best way, it can slowdown your app. Could have been a better approach a direct access.
It's also inefficient to copy structures like in:
Translation oneLine = Translations[i];
Its faster and more effective to use the addressed structure:
const char* GetTranslation( int id )
{
int i;
for(i = 0; i < sizeof(Translations)/sizeof(Translations[0]); i++)
{
if(Translations[i].Structured.id == id)
{
if(_currentLanguageId >= LanguageId_Invalid) {
return("ErrUnknownLanguage");
}
return *(Translations[i].Heap + _currentLanguageId);
}
}
return("ErrNotTranslated");
}
Finally this is my full version:
typedef enum
{
LanguageId_English = 0,
LanguageId_German,
LanguageId_Invalid
}LanguageIds;
typedef struct
{
const char* Translations[LanguageId_Invalid];
int id;
}Translation;
typedef enum
{
NodeId_Languages,
NodeId_EN,
NodeId_DE
}NodeIds;
const Translation Translations[] = {
{ {"Languages", "Sprachen"}, NodeId_Languages },
{ {"German", "Deutsch"}, NodeId_DE },
{ {"English", "Englisch"}, NodeId_EN },
};
const char* GetTranslation( int id )
{
int i;
for(i = 0; i < sizeof(Translations)/sizeof(Translations[0]); i++)
{
if(Translations[i].id == id)
{
if(_currentLanguageId >= LanguageId_Invalid) {
return("ErrUnknownLanguage");
}
return Translations[i].Translations[_currentLanguageId];
}
}
return("ErrNotTranslated");
}
int main(int argc, char *argv[])
{
printf("%s\n", GetTranslation(NodeId_DE));
return 0;
}