取消引用指向char的指针 [英] Dereferencing pointers to pointers of char

查看:109
本文介绍了取消引用指向char的指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好论坛,



好​​消息是这个有效:

Hello forum,

the good news is that this works:

// Header
typedef enum
{
    LanguageId_English  = 0,
    LanguageId_German,
    // Insert additional languages here
    LanguageId_Invalid
}LanguageIds;

// Source
typedef union Translation Translation;
union Translation
{
    struct
    {
        const char* English;
        const char* German;
        // Upon inserting more languages, update LanguageIds as well.
        //   LanguageId_Invalid will grow automatically.
        int id;
    }Structured;
    const char* Heap[LanguageId_Invalid];             // (1) Annoyance
};

// [Edit]
typedef enum
{
    // More values here
    NodeId_Languages,
    NodeId_EN,
    NodeId_DE
    // And still more values here
}NodeIds;
// [/Edit]

const Translation Translations[] = {
    // there are more entries here
    { "Languages", "Sprachen", NodeId_Languages },
    { "German", "Deutsch", NodeId_DE },
    { "English", "Englisch", NodeId_EN },
    /* Note the comma at the end of the previous line.
     * There are even more entries to this.
     * Even those whose last field doesn't originate
     * from the NodeIds enumeration.
     */
};

const char* GetTranslation( int id )
/* Even though every id in this example stems from the
 * NodeIds enumeration,
 * the same is not guaranteed for the entire program when finished.
 */
{
    int i;
    for(i = 0; i < sizeof(Translations)/sizeof(Translations[0]); i++)
    {
        Translation oneLine = Translations[i];
        if(oneLine.Structured.id == id)
        // Got the correct line.
        {
            if(_currentLanguageId >= LanguageId_Invalid) // Which is greater
                                                         // than all other language ids.
            {
                return("ErrUnknownLanguage");
            }
            return(oneLine.Heap[_currentLanguageId]);
        }
    }

    return("ErrNotTranslated");
}



这会调用以上代码:


This calls above code:

const char* output = GetTranslation(NodeId_DE);

我没有提及,但您已经发现这会将应用程序的UI转换为不同的语言(标识符LanguageIds和GetTranslation是适用的提示)。该函数返回可以打印的 const char * 。我想保持这种方式。

[/编辑]



我想摆脱依赖( 1)。但是我让(2)再次工作的努力没有成功。



I didn't mention but you already figured out that this shall translate an application's UI to different languages (the identifiers "LanguageIds" and "GetTranslation" were applicable hints). The function returns a const char* that can be printed. I'd like to keep it that way.
[/Edit]

I'd like to get rid of the dependency at (1). But my efforts to get (2) to work again did not succeed.

// (1)
const char** Heap;

// (2)
return( *(oneLine.Heap + _currentLanguageId));

解除引用的正确方法是什么(1)获取正确的 const char * 要打印吗?

What's the correct way of dereferencing (1) to get the correct const char* to be printf'd?

推荐答案

您的编程示例是一个非常糟糕的混淆函数示例,容易出错和混淆。我建议你退出你的意图并考虑一个更明确的选择,否则在将来的版本中将是一场噩梦。

你在开始时滥用翻译指针的顺序结构制作作为一系列翻译出现在最后。

最糟糕的是,有一个完全合法的模式来实现你想要做的事情。考虑:

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];
	// Upon inserting more languages, update LanguageIds as well.
	//   LanguageId_Invalid will grow automatically.
	int id;
}Translation;



没有更多联盟,一个简单的结构,翻译数组作为第一个字段。



现在为了澄清C概念,让我们分析你的软件。

在工会中你宣布:


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;



那个是一个变量,它包含一个内存位置的地址,其中有一个指向char的指针数组。请仔细阅读!

当您尝试访问数据时:


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));



编译器获取Heap指向的地址作为char指针数组的地址,但它是地址第一个字符串,获取该位置的前4个字节,并将它们视为字符串的地址。程序崩溃......

在平面词中你告诉Heap是数组的地址,但它是数组本身

你必须告诉编译器,在Heap有指针数组时,你的声明必须是:


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)
        // Got the correct line.
        {
            if(_currentLanguageId >= LanguageId_Invalid) // Which is greater
                                                         // than all other language ids.
            {
                return("ErrUnknownLanguage");
            }
            return *(Translations[i].Heap + _currentLanguageId);
        }
    }
 
    return("ErrNotTranslated");
}





最后这是我的完整版:



Finally this is my full version:

// Header
typedef enum
{
    LanguageId_English  = 0,
    LanguageId_German,
    // Insert additional languages here
    LanguageId_Invalid
}LanguageIds;
 
// Source
typedef struct
{
	const char* Translations[LanguageId_Invalid];
	// Upon inserting more languages, update LanguageIds as well.
	//   LanguageId_Invalid will grow automatically.
	int id;
}Translation;

// [Edit]
typedef enum
{
    NodeId_Languages,
    NodeId_EN,
    NodeId_DE
}NodeIds;
// [/Edit]

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)
        // Got the correct line.
        {
            if(_currentLanguageId >= LanguageId_Invalid) // Which is greater
                                                         // than all other language ids.
            {
                return("ErrUnknownLanguage");
            }
            return Translations[i].Translations[_currentLanguageId];
        }
    }
 
    return("ErrNotTranslated");
}

int main(int argc, char *argv[])
{
	printf("%s\n", GetTranslation(NodeId_DE));

	return 0;
}


这篇关于取消引用指向char的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆