相关疑难解决方法(0)

优化"while(1);" 在C++ 0x中

更新,见下文!

我听说并读过C++ 0x允许编译器为以下代码段打印"Hello"

#include <iostream>

int main() {
  while(1) 
    ;
  std::cout << "Hello" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

它显然与线程和优化功能有关.在我看来,这可能让许多人感到惊讶.

有人能够很好地解释为什么必须允许这样做吗?作为参考,最新的C++ 0x草案说明了6.5/5

在for语句的情况下,在for-init语句之外的循环,

  • 不调用库I/O函数,和
  • 不访问或修改易失性对象,以及
  • 不执行同步操作(1.10)或原子操作(第29条)

可以通过实现来假设终止.[注意:这是为了允许编译器转换,例如删除空循环,即使无法证明终止也是如此. - 结束说明]

编辑:

这篇富有洞察力的文章谈到了标准文本

不幸的是,没有使用"未定义的行为".但是,只要标准说"编译器可以假设P",就暗示具有非-P属性的程序具有未定义的语义.

这是正确的,是否允许编译器为上述程序打印"Bye"?


这里有一个更有见地的线索,这是关于C的类似改变,由Guy完成上述链接文章开始.在其他有用的事实中,他们提出了一个似乎也适用于C++ 0x的解决方案(更新:这将不再适用于n3225 - 见下文!)

endless:
  goto endless;
Run Code Online (Sandbox Code Playgroud)

看来,编译器不允许优化它,因为它不是循环,而是跳转.另一个人总结了C++ 0x和C201X的建议更改

通过编写一个循环,程序员断言或者环路不可见的东西的行为(执行I/O,访问volatile对象,或执行同步或原子操作), 或者,它最终会终止.如果我通过编写一个没有副作用的无限循环来违反这个假设,我对编译器撒谎,而我的程序的行为是未定义的.(如果我很幸运,编译器可能会警告我.)语言不提供(不再提供?)表达无可见行为的无限循环的方法.


2011年3月3日更新为n3225:委员会将案文移至1.10/24并说

实现可以假定任何线程最终将执行以下操作之一:

  • 终止,
  • 调用库I/O函数,
  • 访问或修改易失性对象,或
  • 执行同步操作或原子操作.

goto把戏,工作了!

c++ optimization loops c++11

150
推荐指数
5
解决办法
1万
查看次数

如果没有循环或条件语句从1到1000打印的C代码如何工作?

我发现C代码打印从1到1000没有循环或条件:但我不明白它是如何工作的.任何人都可以通过代码解释每一行吗?

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}
Run Code Online (Sandbox Code Playgroud)

c function-pointers

148
推荐指数
2
解决办法
8674
查看次数

如何驱动C#,C++或Java编译器在编译时计算1 + 2 + 3 + ... + 1000?

在最近的一次采访中,我被问到一个非常奇怪的问题.面试官问我如何使用编译器功能计算1 + 2 + 3 + ... + 1000.这意味着我不允许编写程序并执行它,但我应该编写一个程序,可以驱动编译器在编译时计算这个总和,并在编译完成时打印结果.作为提示,他告诉我,我可能会使用编译器的泛型和预处理器功能.可以使用C++,C#或Java编译器.有任何想法吗???

这个问题与计算总和无关,这里没有任何循环问题.此外,应该注意,总和应该在编译期间计算.不能使用C++编译器指令打印结果.


阅读更多关于发布的答案,我发现在使用C++模板编译期间解决问题称为元编程.这是Erwin Unruh博士在标准化C++语言过程中偶然发现的一种技术.您可以在元编程的wiki页面上阅读有关此主题的更多信息.似乎可以使用Java注释在Java中编写程序.您可以在下面看看maress的答案.

关于C++的元编程一个很好的书是这一个.如果感兴趣,值得一看.

一个有用的C++元编程库是Boost的MPL 这个链接.

c# c++ java compiler-construction metaprogramming

121
推荐指数
9
解决办法
8407
查看次数

显示从1到100的数字,没有循环或条件

有没有办法从1到100打印数字而不使用任何循环或条件,如"如果"?我们可以很容易地使用递归但是又有一个if条件.有没有办法不使用"if"?也没有重复的打印语句,或包含1到100之间所有数字的单个打印语句.

Java中的解决方案更可取.

java loops

33
推荐指数
18
解决办法
10万
查看次数

编译时递归如何工作?

我在这里找到了一个代码打印1到1000没有循环或条件

有人可以解释编译时间递归是如何工作的,无法在谷歌中找到它

// compile time recursion
template<int N> void f1()
{ 
    f1<N-1>(); 
    cout << N << '\n'; 
}

template<> void f1<1>() 
{ 
    cout << 1 << '\n'; 
}


int main()
{
    f1<1000>();
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

c++ compile-time

21
推荐指数
1
解决办法
2500
查看次数

如何在 for 循环中使用 const 变量来生成模板类?

我有一个像

template <size_t N>
class A
{
    template <size_t N>
    someFunctions() {};
};
Run Code Online (Sandbox Code Playgroud)

现在我想创建类的实例并在 for 循环中为一组许多值调用其中的函数,例如

// in main()

int main()
{
    for (int i = 1; i <= 100; i++)
    {
        const int N = i;  // dont know how to do this
        A<N> a;
        a.functionCalls();
    }
}

Run Code Online (Sandbox Code Playgroud)

这该怎么做?希望有一种方法可以做到这一点。

c++ templates for-loop compile-time-constant template-classes

15
推荐指数
3
解决办法
412
查看次数

指针算术是否在数组之外使用?

我认为我对指针算法的语义相当了解,但在处理数组时我只看到过例子.是否有任何其他用途不能通过不透明的手段实现?我相信你可以找到一种巧妙的方法来使用它来访问结构的成员,但我不知道为什么你会打扰.我最感兴趣的是C,但我会用C++标记,因为答案可能也适用于那里.

根据到目前为止收到的答案进行编辑:我知道指针可以在许多非数组上下文中使用.我特别想知道关于指针的算术,例如递增,有所作为等.

c c++

14
推荐指数
4
解决办法
1751
查看次数

错误既不是语法也不是语义?

我在家庭作业上有这个问题(不用担心,已经完成):

[使用您最喜欢的命令式语言,给出每个...的示例]编译器既无法捕获也无法轻松生成要捕获的代码的错误(这应该违反语言定义,而不仅仅是程序错误)

来自"编程语言语用学"(第3版)Michael L. Scott

我的回答,称mainmain通过传递相同的参数(在C和Java),灵感来自.但我个人觉得这只是一个语义错误.

对我来说,这个问题是在询问如何产生一个既不是语法也不是语义的错误,坦率地说,我无法想到它不会陷入其中的情况.

是否容易被利用的代码,如缓冲区溢出(以及我从未听说过的其他利用)?某种坑从语言结构中掉落(IDK,但懒惰的评估/弱类型检查)?我想在Java/C++/C中使用一个简单的例子,但欢迎其他例子.

c c++ java syntax semantics

11
推荐指数
2
解决办法
1743
查看次数

编译时间递归和条件

我正在阅读"打印1到1000没有循环或条件"的响应,我想知道为什么有必要在最佳答案中使用NumberGeneration <1>的特殊情况.

如果我删除它并在模板中添加N == 1的检查(下面的代码),代码将无法编译"模板实例化深度超过最大值",但我不确定原因.条件在编译时是否处理不同?

#include <iostream>

template<int N>
struct NumberGeneration
{
    static void out(std::ostream& os)
    {
        if (N == 1)
        {
            os << 1 << std::endl;
        }
        else
        {
            NumberGeneration<N-1>::out(os);
            os << N << std::endl;
        }
    }
};

int main()
{
    NumberGeneration<1000>::out(std::cout);
}
Run Code Online (Sandbox Code Playgroud)

c++ compile-time

9
推荐指数
1
解决办法
1100
查看次数

不使用循环打印1到1000

我在c ++编程上下文中看到了这个问题,我检查了一个解决方案,我的一个朋友给我这个代码它的工作完美,但我无法理解它的逻辑以及它是如何工作的.我向他询问了这件事,但他也不知道该程序是如何实际运作的,我认为他也是从某个地方采取这个解决方案.任何人都可以解释这个我的意思背后的逻辑 (&main + (&exit - &main)*(j/1000))(j+1);吗?

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

c

9
推荐指数
1
解决办法
2489
查看次数