【问题标题】:C Idioms and little known facts [closed]C成语和鲜为人知的事实[关闭]
【发布时间】:2009-12-29 17:44:33
【问题描述】:

好的,我在这里看到了很多关于 C 中奇怪的习语和常见做法的帖子,这些帖子最初可能并不直观。或许可以举几个例子

数组中的元素:

#define ELEMENTS(x) (sizeof (x) / sizeof (*(x)))

Odd array indexing:

a[5] = 5[a]

Single line if/else/while/for safe #defines

#define FOO(X) do { f(X); g(X); } while (0)
#define FOO(X) if (1) { f(X); g(X); } else

我对 C 程序员专家的问题是:惯用语实践代码片段鲜为人知的事实 经常出现在 C 代码中,但可能不是很直观,但可以很好地了解 C 编程?

【问题讨论】:

  • 应该是社区维基
  • 太糟糕了,它被关闭了,机器人不是一个问题......

标签: c arrays macros


【解决方案1】:

用于从n-1 倒计时到0 的“箭头运算符”:

for ( int i = n; i --> 0; ) ...

这不是很常见,但它是一个有趣的说明,在某些方面for 循环的初始化/测试/更新部分是约定俗成的。这是通常的模式,但您仍然可以在其中放置任意表达式。

这也是关于词法分析如何工作的一个很好的小提醒。

【讨论】:

  • 这个强大的运营商根本无法逃脱。
  • 适合线性搜索。毕竟,您应该首先查看的位置是您放置东西的最后一个位置。
  • 我看到这仍然是我唯一的单一反对票。尽管这个答案很受欢迎,但我出于几个原因拒绝了它,其中最重要的一点是你从未解释过它是如何工作的,或者考虑到更正统、不那么晦涩和更容易理解的代码的可用性,为什么人们会使用它。
【解决方案2】:

反正有人会提,还不如说是我:Duff's Device

它很好地说明了标签在 C 中的工作方式,理解它让我第一次有了“啊哈体验”。这是他的原始代码:

send(to, from, count)
register short *to, *from;
register count;
{
    register n=(count+7)/8;
    switch(count%8){
    case 0: do{ *to = *from++;
    case 7:     *to = *from++;
    case 6:     *to = *from++;
    case 5:     *to = *from++;
    case 4:     *to = *from++;
    case 3:     *to = *from++;
    case 2:     *to = *from++;
    case 1:     *to = *from++;
        }while(--n>0);
    }
}

今天,人们不会使用register,并避免使用旧式函数定义。

【讨论】:

  • 另外,据我了解,您不想在现代优化编译器上执行此操作——您只会妨碍它。
  • @dubiousjim 我不这么认为,如果它是一个内存映射端口。现代优化编译器可能会将所有这些副本合二为一。
【解决方案3】:

逗号操作符,虽然文档完善(K&R 等)出现在相当多的算法代码中,并且常常让许多以前没有遇到过它的程序员感到惊讶。它通常用于简化一些循环结构:

#define kITERATIONS_MAX 10
int i=0,j=0,array[kITERATIONS_MAX],outArray[kITERATIONS_MAX],temp=0;

for (i=0,j=kITERATIONS_MAX-1; i < kITERATIONS_MAX; i++,j--)
{
temp = array[i]*array[j];
outArray[i]=temp;
}

上面的代码将数组元素 0 到 9 与 9 到 0 相乘,同时避免嵌套循环。

使用逗号运算符时,第一个和第二个表达式都被计算。忽略第一个表达式的结果,返回第二个表达式的结果。

【讨论】:

  • 我在while 条件中使用逗号运算符来做两件事,通常是赋值后跟一个测试:while (c = getc(), c != EOF) ...
  • @DavidRTribble c = getc() 的计算结果等于c,这意味着您可以(大概)使用while((c = getc()) != EOF) ...
  • @RobbieMckennie,确实如此,但我发现将这两个操作(赋值和比较)作为控制 while 表达式中的两个单独的表达式来阅读更容易。
  • @DavidRTribble 但是连接表达式的计算结果也不太清楚
  • 这里避免了什么样的嵌套循环?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 2011-03-05
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-06-17
  • 2010-10-04
相关资源
最近更新 更多