【问题标题】:How do you optimize this?你如何优化这个?
【发布时间】:2012-07-27 15:13:26
【问题描述】:

我有一个这样的结构:

static struct F_t {
  char *_1;
  char *_2;
  char *_3;
  char *_4;
  char *_5;
  char *_6;
  char *_7;
  char *_8;
  char *_9;
  char *_10;
  char *_11;
  char *_12;
} F = { 0 };

根据标准输入的一些值,它设置正确。

“问题”是我从字符串中检索它,我需要正确设置它。我目前正在使用这个功能:

static inline void 
setf(int i, char *value)
{
  /* Nothing to do. */
  if(i > 12)
    return;

  if(i == 1)
    F._1 = value;
  else if(i == 2)
    F._2 = value;
  else if(i == 3)
    F._3 = value;
  else if(i == 4)
    F._4 = value;
  else if(i == 5)
    F._5 = value;
  else if(i == 6)
    F._6 = value;
  else if(i == 7)
    F._7 = value;
  else if(i == 8)
    F._8 = value;
  else if(i == 9)
    F._9 = value;
  else if(i == 10)
    F._10 = value;
  else if(i == 11)
    F._11 = value;
  else if(i == 12)
    F._12 = value;
}

我尝试过使用宏.. 但由于它是在运行时设置的,所以这是不可能的。我知道如果没有反思,像这样的现代事物等等。但也许有一些我不知道的东西。可能在 C++ 中是可能的。但不是。我要纯C。

任何建议都非常重视。提前致谢。

【问题讨论】:

  • 为什么不使用数组?
  • 源代码可能看起来有点笨拙,但我敢打赌编译器在幕后做了完全正确的事情。
  • @ams - 我的 GCC 4.4 副本不适用于 -O3。它为赋值生成 12 个基本块,并为这些块生成 12 个条件跳转。
  • 令人失望。我以为编译器会将其转换为开关表和 DTRT,但事实并非如此。我已经测试了 4.6.3 仍然没有乐趣。

标签: c optimization if-statement


【解决方案1】:

你为什么不这样做:

static struct F_t {
    char ** _;
} F = { 0 };

此时,只需确保您 malloc 为大小为 12 的双精度数组(在您的情况下),然后您就可以拥有如下功能:

setf(int i, char *value)
{
     F._[i] = value;
}

事情看起来好多了,不是吗?

【讨论】:

  • 我喜欢这个答案。但是,当您可以使用char * _[12] 在结构中声明一个包含 12 个指针的数组时,为什么要malloc?
  • 我同意char * _[12] 会更好。最好也给它起个名字。
  • @ArjunShankar 我同意你们两个。我只是觉得这样更有用。
  • @MichałGórny 就名字而言,我只是想保持一致。
  • @Flo - 如果 OP 已经在创建一个包含 12 个元素的结构,那么使用 char ** 而不是 char*[12] 就不会获得额外的用处。 OP 希望永远使用 12 个元素,不多也不少。相反,char** 让您容易受到内存管理错误的影响。
【解决方案2】:

除了强烈建议考虑@PhillipNordwall 的使用数组的建议。假设编译器将打包结构字段而不在它们之间进行任何类型的填充,这可能会起作用。

static inline void 
setf(int i, char *value)
{
   char **p = &F._1;  /* obtain the address of the first field in the struct */
   p+= i - 1;         /* add an offset to the address according to index */
  /* Nothing to do. */
  if(i > 12)
    return;

   *p = value;        /* set the field's value */
}

【讨论】:

  • 对不起,应该在if语句之前声明p变量,C++风格的声明很难放弃;)
  • @Kakashi,这些天我几乎不再使用 C 或 C++ 进行编程,但我仍然喜欢这些语言 - (C 比 C++ 多一点 - 具有强大模板元编程的现代 C++ 对我来说很难消化)。很高兴得知 C 采用了 C++ 风格的声明,我喜欢我的变量靠近使用它们的代码... ;)
  • 对于您名字中的拼写错误,我很抱歉 Phillip!感谢您的编辑。
【解决方案3】:

试试这个:

static inline void  setf(int i, char *value) 
{
    char** F_as_array = (char**)(&F._1);

    if (i > 12 || i < 1) 
        return;

    F_as_array[i-1] = value; 
}

(我没有编译,但我认为它可以工作)

编辑:F_as_array[i] -> F_as_array[i-1] (根据您提供的代码,我假设第一个索引是 1)

【讨论】:

  • @MichałGórny - 我现在懒得阅读 C99 PDF 来验证您是否正确,但请查看 this question。如果您仍然确定它会失败,您也应该考虑发布该问题的正确答案。
  • 我很久以前也假设过这样的事情,但现代编译器似乎并没有严格遵守这一点。将一个完全不同类型的对象转换为另一个对象只是一种非常糟糕的做法,即使任何符合标准的编译器都应该能够处理它。
  • 我必须同意 MichałGórny 的观点,即这是一种不好的做法,因为他提到了(对齐)。但是,不幸的是,我曾参与过一些使用自动代码生成工具来声明全局数据变量的项目。 (这是项目的一个约束。)该工具根本不声明数组。这就是为什么我们唯一的方法是禁用对齐并使用我在此处提供的解决方案。为了在 GCC 编译器中执行此操作:#define packed_data __attribute__((__packed__))。只是一个小修复,我没有注意到第一个索引是'1'。我会在我原来的答案中修复它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 2017-04-10
  • 2014-09-09
相关资源
最近更新 更多