【问题标题】:C/C++ local variable nuanceC/C++ 局部变量的细微差别
【发布时间】:2014-03-08 08:22:01
【问题描述】:

好的,在我发布这个问题之前,我肯定知道这个社区中有这些所谓的“专业人士”指责我过早的优化。让我说清楚:我想确定我到底在写什么,即使它在函数内部的堆栈级别是这样的细微差别。 我有一个多维数组,我知道为了访问数据,您需要访问这些索引变量,然后访问数组本身,这会占用大量时间。所以我这样做了:

 char* ref = gdata.mapnames[game.maptype][game.map];
 size_t a = strlen(ref) - 4;
 ref[a] = '\0';
 strcpy(temppath, ref);
 ref[a] = '.';`

我将多维数组“包装”在一个用作指针的简单局部变量中。由于我必须多次访问同一个数组,这种方法可以节省查找时间并因此节省运行速度吗?当然理论上,由于现在的处理器是如此之快,你不会看到任何区别,除非我编写更大的应用程序需要这个。多维数组不是坏习惯吧?

【问题讨论】:

  • 多维数组当然不是一个坏习惯。但是,我不知道您要加快什么速度。
  • 在这种情况下缓存数组元素查找的结果是个好主意。有些人确实将常识称为过早的优化,不要对此感到沮丧。
  • 你为什么要ref[a] = '\0'strlen 仅在 ref 指向字符串时才有效,即以空字符结尾的字符数组,否则会出错。
  • 您的代码对我来说似乎是过早的未优化。为什么你扫描ref 两次而不是一次?为什么要对ref[a] 进行两次冗余写入?
  • 你没有优化任何东西。您专注于确保编译器不愚蠢(它们不再愚蠢),而不是专注于使您的算法更好(编译器无法为您优化)优化您的算法,然后使用 -O3 或其他任何东西进行编译最大优化。如果您认为尚未进行此类优化,请检查生成的程序集。

标签: c arrays performance


【解决方案1】:

首先,不要使用strcpy,这很危险,请改用strncpy。关于您的问题,编译器会为您完成所有这些事情,不用担心查找任何内容。

【讨论】:

  • 对我来说,dangerous 听起来有点刺耳。如果满足不变量(有足够的空间),它就是安全的。
  • strcpy 和 strncpy 做的事情完全不同,一个不是直接交换另一个。考虑到他关心微优化,推荐一个可能会写入数千个额外字节的函数是没有意义的。如果您知道源和目标的长度,strcpy 就没有任何问题。
【解决方案2】:

在 C++ 中,由于运算符重载,mapnames[i] 实际上可能是一个函数调用。换句话说,可以执行相当复杂的代码。在 C 中,这只是指针运算。 您的编译器是否对此进行了优化取决于很多因素,包括平台、版本和变量限定符。唯一可以确定的方法是检查汇编输出。 在这种情况下,我认为使用临时变量更具可读性。

【讨论】:

    【解决方案3】:

    使用一个半胜任的优化器,这绝对不会影响速度,并且可能会产生完全相同的机器代码(除非您正在处理线程代码和一个对多个线程可见的数组),但使用临时变量使代码更容易编写和阅读。但是,我会将大部分代码块的其余部分重写为:

    ssize_t a = strlen(ref) - 4;
    if( a < 0 ) a = 0;
    if( a >= sizeof( temppath ) ) a = sizeof(temppath)-1; /* assumes temppath is an array */
    strncpy( temppath, ref, a );
    temppath[a] = 0;
    

    解释:如果( ref ) 的长度小于 4 个字节,size_t 将作为一个非常大的数字结束,因为 size_t 是无符号的。 ssize_t 是有符号的,因此它将是一个负值。接下来,进行边界检查。我将 strncpy 与空终止符一起使用,因为如果不需要,通常最好避免修改字符串输入。

    edit 实际上,除非优化器知道数组的内容在函数执行过程中是不可变的,或者 gdata.mapnames[game.maptype][game.map] 实际上是一个字符[] 数组,不能缓存 ref,但是可以缓存 &gdata.mapnames[game.maptype][game.map]。

    【讨论】:

    • 感谢您的意见!
    • 然而,确保 ref 至少为 4 个字节,因为另一个函数仅从扩展名为 .map 的文件加载数组,已经保证了 4 个字符(字节)。我自己写了这个函数,所以我很确定。
    猜你喜欢
    • 2012-11-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2022-06-16
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多