【问题标题】:C/C++ Post-increment by more than oneC/C++ 后增量超过一
【发布时间】:2011-07-18 15:40:06
【问题描述】:

我正在从缓冲区读取字节。但有时我正在阅读的是一个单词或更长的内容。

// assume buffer is of type unsigned char *
read_ptr(buffer+(position++))

这很好,但我怎样才能将位置增加 2 或 4?我无法让+= 运算符进行后增量,是吗?

原因是,我想要评估这个可怕的大表达式,同时增加位置变量。

我想我想出了自己的解决方案。我很确定它有效。但是每个人都会讨厌它,因为这不是可读的代码。

read_ptr(buffer+(position+=4)-4)

我会在对其进行一些测试以确保它在做正确的事情后将其制成一个宏。

结论:

不要这样做。这只是一个坏主意,因为这种事情会产生不可维护的代码。但是......将任何预递增运算符转换为后递增运算符确实非常容易。

【问题讨论】:

  • 不要那样做。编写代码清晰易读。像这样滥用操作符只会让你在应用崩溃时哭泣。
  • 请注意,增加指针并不一定意味着指针的新值相差 1 个字节。
  • 而且,更重要的是,如果我们必须保持这种怪物,它会让 我们 哭泣。您应该始终假设继承您的代码的人是一个知道您住在哪里的精神病患者:-)
  • 在所有回复之后,看到那个编辑让我面对。 =(
  • 感谢大家的优秀cmets。在这个网站上,当人们对我提出的任何问题挑剔每一个潜在问题时,有时感觉就像是错过了。然后我意识到所有阅读这个网站的人都会从中受益,而不仅仅是我。这就是 SO 规则的原因。

标签: c++ c operators post-increment


【解决方案1】:

我怎样才能将position 增加 2 或 4?

您不能将变量后增加 2 或 4,但您可以使用以下(在您的情况下)

read_ptr(buffer+position); position += 2;

【讨论】:

  • 这不是后增量,Prasoon!
  • 如果您只是替换 ,带有;。我知道,你的显示器上有更多的电子,或者你的纸上有一些墨水,但为了可读性,这不值得吗? :-)
  • @paxdiablo :但是效果是一样的,不是吗?但是,正如您提到的,就可读性而言,; 要好得多。
  • @Prasoon,“不是吗?”是问题所在。我必须去查看标准,看看, 是否是一个序列点,保证顺序。我知道 ; 会保证它,, 可以保证它,但我的年龄太高了,我不必担心它 :-) 但是,既然你改了,+1。
  • “我必须去查看标准,看看 , 是否是一个序列点”——所以问题是我们是为知道逗号运算符做什么的维护程序员编写代码,还是为维护程序员编写代码没有的程序员。这是 C++ 中的一个普遍问题,我认为,“我们可以假设以下人员的能力:(a) 典型,(b) 最坏的情况,程序员。最明显的答案是,“他们和我一样了解” , 是错误的,第二个最明显的是,鉴于 C++ 的强大功能可以做一些聪明但有点模糊的事情,“他们一无所知”过于局限。
【解决方案2】:

虽然我不推荐这种解决方案,但如果您不想在代码中更改此行:

read_ptr(buffer+(position++));

而你还想将position 增加2,然后将位置定义为Index position(2);,这里定义了Index 类型,并展示了用法:

struct Index
{
    int step;
    int value;
    Index(int s=1, int v=0): step(s), value(v) {}
    Index operator++(int) 
    { 
       Index prev(step, value); 
       value += step; 
       return prev;
    }
    operator int() { return value; }
};

int main() {
        char arr[] = "1234567890" ;

        cout <<"Increment by 2" <<endl;
        Index i2(2); //increment by 2
        cout << *(arr + (i2++)) << endl;
        cout << *(arr + (i2++)) << endl;
        cout << *(arr + (i2++)) << endl;
        cout << *(arr + (i2++)) << endl;

        cout <<"Increment by 3" <<endl;        
        Index i3(3); //increment by 3
        cout << *(arr + (i3++)) << endl;
        cout << *(arr + (i3++)) << endl;
        cout << *(arr + (i3++)) << endl;
        cout << *(arr + (i3++)) << endl;
        return 0;
}

输出:

Increment by 2
1
3
5
7
Increment by 3
1
4
7
0

工作示例:http://ideone.com/CFgal

注意:我仍然不会在现实生活项目中建议此解决方案。这更像是谜题:D

【讨论】:

  • 哇。现在这把它带到了另一个层次。它绝对比我想出的解决方案更具可读性......
  • @Steven:如果是拼图或玩 C++,那么你可以做这样的体操。但不要在实际项目中这样做!
  • 确实如此。有没有办法拥有一个可参数化的后增量运算符?就像,重新定义 += 运算符以使其通过正确的操作数后置而不是前置递增。
  • @Steven:是的。你也可以重载operator+
【解决方案3】:

+= 运算符将是一个单独的语句(不是 post 或 pre increment)。您可以使用以下行:

func(buffer + position); position += 2;

【讨论】:

    【解决方案4】:

    你没有;你把它分成不止一行。这里没有理由把所有东西都塞进一行。

    read_ptr( buffer + position );
    position += n;
    

    【讨论】:

    • “后增量”意味着两行应该交换。
    • 将所有内容都塞进一行的原因是它是否被用作表达式而不仅仅是一个语句。
    • @StevenLuL 但这不是真正的要求。没有理由将这一切都推到一条线上,如果这样做,你的情况会更糟。
    【解决方案5】:

    好吧,我确实在编辑中回答了我的问题...基本上我想要的是一个表达式,它的计算结果为原始值,但具有任意递增的副作用。这里有一些宏。

    #define INC(x,inc) (((x)+=(inc))-(inc))
    #define INC2(x) INC(x,2)
    #define INC4(x) INC(x,4)
    #define INC8(x) INC(x,8)
    

    【讨论】:

      【解决方案6】:

      如果position 是指向int16int32 的指针,则递增它将分别增加2 或4。

      【讨论】:

      • 是的,我认为实现我想要的(某种)的另一种方法是增加指针本身,只要它是适当的类型。然后可以使用++ 运算符。
      【解决方案7】:

      在 C++ 中,您可以轻松编写一个函数来执行后置式双增量:

      template <typename T>
      T inc2(T &t) {
          T r(t);
          ++t; // or t++ if you want to respect inconsistently-overloaded operators,
          ++t; // but I wouldn't bother.
          return r;
      }
      
      read_ptr(buffer+inc2(position))
      

      在 C 中稍微有点尴尬:

      size_t inc2(size_t *s) { // or whatever type you're using
          size_t r = *s;
          (*s) += 2;
          return r;
      }
      
      read_ptr(buffer+inc2(&position))
      

      您也可以通过将其作为附加函数参数或在 C++ 情况下作为附加模板参数来涵盖第 4 种情况。

      还有第二个问题,是否值得在 C++ 或 C 中追求这种编程风格,在这种情况下,您可以在一条语句中完成这么多。避免副作用可以使代码更容易理解,即使它出现的时间更长。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-03
        • 2012-06-01
        • 2012-04-24
        • 2012-01-24
        • 2012-08-06
        • 1970-01-01
        • 1970-01-01
        • 2012-10-17
        相关资源
        最近更新 更多