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

123
在最近一次面试中,我被问到一个非常奇怪的问题。面试官问我如何仅使用编译器功能计算1+2+3+...+1000。这意味着我不能编写程序并执行它,而是应该编写一个能够在编译时驱动编译器计算此总和并在编译完成时打印结果的程序。作为提示,他告诉我可以使用编译器的泛型和预处理器功能。可以使用C++、C#或Java编译器。有什么想法吗?
需要注意的是,这个问题与在没有任何循环的情况下计算总和无关,详情请参见此处。此外,必须在编译期间计算总和。仅使用C++编译器指令打印结果是不可接受的。
阅读了更多关于发布的答案的内容,我发现使用C++模板在编译期间解决问题被称为元编程。这是由Erwin Unruh 博士在标准化C++语言的过程中意外发现的技术。如果感兴趣,可以在元编程的wiki页面上了解更多关于此主题的信息。看来可以使用Java注释编写程序。你可以查看下面maress的答案。
一本关于C++元编程的好书是这本,如果感兴趣值得一看。
一个有用的C++元编程库是Boost的MPL,请点击此链接

17
编译错误算作“完成”吗?翻译完成。 - Mysticial
4
这个提示实际上是让你使用C++模板。显然不完全相同,但这个代码片段是用于打印1到1000的,我相信你可以修改它来添加到一千... https://dev59.com/9W455IYBdhLWcg3wD_oB - Joe
8
const int value = 1 + 2 + 3.... + 1000; Console.WriteLine(value);这段代码的意思是:定义一个整型常量value,其值为从1加到1000的结果,然后使用Console.WriteLine方法将value输出到控制台。 - George Duckett
9
有时候我觉得,有些面试问题仅仅是为了证明面试官在智力上比被面试者更加优越。 - Chris
4
在被问到这个问题之前,你有要求过很多钱吗? - Salman A
显示剩余13条评论
13个回答

119

更新 现在递归深度有所改进!可以在MSVC10和GCC上工作而不需要增加深度。 :)


简单的编译时递归加法:

template<unsigned Cur, unsigned Goal>
struct adder{
  static unsigned const sub_goal = (Cur + Goal) / 2;
  static unsigned const tmp = adder<Cur, sub_goal>::value;
  static unsigned const value = tmp + adder<sub_goal+1, Goal>::value;
};

template<unsigned Goal>
struct adder<Goal, Goal>{
  static unsigned const value = Goal;
};

测试代码:

template<unsigned Start>
struct sum_from{
  template<unsigned Goal>
  struct to{
    template<unsigned N>
    struct equals;

    typedef equals<adder<Start, Goal>::value> result;
  };
};

int main(){
  sum_from<1>::to<1000>::result();
}

GCC的输出:

错误:声明‘struct sum_from<1u>::to<1000u>::equals<500500u>’

在Ideone上的实时示例

MSVC10的输出:

error C2514: 'sum_from<Start>::to<Goal>::equals<Result>' : class has no constructors
      with
      [
          Start=1,
          Goal=1000,
          Result=500500
      ]

@hsalimi:我编辑了答案,实际展示了一些完成任务的代码。 :) - Xeo
哇,你真的让我印象深刻 :-) - TonySalimi
@hsalimi:这项技术是由Erwin Unruh博士在1997年于斯德哥尔摩的C++标准化会议上发明的。他计算了一系列质数。 - Dietmar Kühl
为了使其不使用递归而正常工作,您可以使用公式N*(N+1)/2来计算总和。 - Adam Gritt
2
如果你想看更多关于C++模板元编程的精彩例子,我建议阅读Andrei Alexandrescu的《现代C++设计》(http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315)。@hsalimi - AVH
显示剩余3条评论

90

C#编译时出错的示例。

class Foo
{
    const char Sum = (1000 + 1) * 1000 / 2;
}

会产生以下编译错误:

Constant value '500500' cannot be converted to a 'char' 

4
@ildjarn,C++模板的答案与这个答案之间存在差异:这里的方法仅因为常量折叠而起作用,而模板允许任意(?)代码。将其分配给一个字符仍然是个好主意! - Voo
@Voo 是的,但公正地说,对于这种编程来说,C#与C++相比就不行了。 - Marlon
3
@Marion 我真的不认为这是语言设计上的错误 ;) 模板元编程可能非常强大,但其他语言仍然可以使用其他解决方案完成大部分工作,而这些解决方案没有那么多陷阱。我曾经参与过一个项目,需要花费几个小时才能编译(不完全正确 - 如果我们没有增加递归实例化限制,它会在几秒钟内失败),而且很难维护。这可能是我不太喜欢它的原因之一。 - Voo
@Voo:FredOverflow的方法也依赖于常量折叠。至于编译速度慢,那就怪你的编译器,而不是语言本身(提示--Clang编译C++非常快)。 - ildjarn
@ildjarn Clang编译极其复杂、嵌套深度极高且非常复杂的模板速度快?我认为一切皆有可能,而且我已经无法再测试它了(谢天谢地),但我无法想象。此外,我在这里谈论的是Xeo的方法,而不是Fred的方法。 - Voo
@Voo: 是的,没错——Clang 编译极其复杂、非常嵌套且非常复杂的模板的时间复杂度是线性的,而 GCC 则使用四次方的时间复杂度来编译它们(或者过去曾经这样——我听说最近相对较新的版本可能解决了这个问题,可能在 4.5 或以上版本中?),而 VC++ 的编译效率甚至比这更糟糕。 - ildjarn

51

我只需要编写一个程序,在编译时驱动编译器计算这个总和,并在编译完成后打印结果。

一个流行的技巧是尝试使用想要打印的数字实例化的模板的不存在成员,从而在编译期间打印数字。

template<int> struct print_n {};

print_n<1000 * 1001 / 2>::foobar go;

编译器会接着输出:

error: 'foobar' in 'struct print_n<500500>' does not name a type

为了演示这个技巧的更加有趣的例子,请参见编译时解决八皇后问题


你可以让print_n保持未定义状态,参见我的回答。 - Xeo
2
@David 但是高斯需要一个聪明的方法,他没有计算机可以快速地完成愚蠢的方式。 - Daniel Fischer

31

由于面试问题中没有指定编译器或语言,我敢用GHC在Haskell中提交一个解决方案:

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Main where

main :: IO ()
main = print $(let x = sum [1 :: Int .. 1000] in [| x |])

将其编译:

$ ghc compsum.hs
[1 of 1] Compiling Main             ( compsum.hs, compsum.o )
Loading package ghc-prim ... linking ... done.
<snip more "Loading package ..." messages>
Loading package template-haskell ... linking ... done.
compsum.hs:6:16-56: Splicing expression
    let x = sum [1 :: Int .. 1000] in [| x |] ======> 500500
Linking compsum ...

我们也得到了一个可运行的程序。


20

有了C++11,生活将变得轻松得多,因为它添加了constexpr函数用于编译时计算,尽管它们当前仅由gcc 4.6或更高版本支持。

constexpr unsigned sum(unsigned start, unsigned end) {
    return start == end ? start :
        sum(start, (start + end) / 2) +
        sum((start + end) / 2 + 1, end);
}

template <int> struct equals;
equals<sum(1,1000)> x;

标准只要求编译器支持512层的递归深度,因此仍需要避免线性递归深度。这是输出结果:

$ g++-mp-4.6 --std=c++0x test.cpp -c
test.cpp:8:25: error: aggregate 'equals<500500> x' has incomplete type and cannot be defined

当然,你可以直接使用公式:

constexpr unsigned sum(unsigned start, unsigned end) {
    return (start + end) * (end - start + 1) / 2;
}

// static_assert is a C++11 assert, which checks
// at compile time.
static_assert(sum(0,1000) == 500500, "Sum failed for 0 to 1000");

1
+1,完全忘记了constexpr。也许我只是太喜欢模板了。 :( - Xeo
这是一个很好的使用constexpr来解决问题的例子(请参见Adder实现):http://kaizer.se/wiki/log/post/C++_constexpr_foldr/。 - Matt
那个公式可能会溢出;最后一步是 / 2,所以为了处理可能的“unsigned”结果的完整范围,你要右移的值必须是n+1位宽,但它不是。可以重新排列公式来避免这种情况,就像clang针对运行时变量范围所做的那样:https://godbolt.org/z/dUGXqg显示clang知道闭合形式的公式并使用它来优化`total += i`循环。 - Peter Cordes

14

在Java中,我考虑使用注解处理。apt工具会在实际解析源文件之前扫描源文件。

在编译源文件时,输出将被打印出来:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyInterface {

    int offset() default 0;

    int last() default 100;
}
处理器工厂:
public class MyInterfaceAnnotationProcessorFactory implements AnnotationProcessorFactory {

    public Collection<String> supportedOptions() {
        System.err.println("Called supportedOptions.............................");
        return Collections.EMPTY_LIST;
    }

    public Collection<String> supportedAnnotationTypes() {
        System.err.println("Called supportedAnnotationTypes...........................");
        return Collections.singletonList("practiceproject.MyInterface");
    }

    public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment ape) {
        System.err.println("Called getProcessorFor................");
        if (set.isEmpty()) {
            return AnnotationProcessors.NO_OP;
        }
        return new MyInterfaceAnnotationProcessor(ape);
    }
}

实际的注解处理器:

public class MyInterfaceAnnotationProcessor implements AnnotationProcessor {

    private AnnotationProcessorEnvironment ape;
    private AnnotationTypeDeclaration atd;

    public MyInterfaceAnnotationProcessor(AnnotationProcessorEnvironment ape) {
        this.ape = ape;
        atd = (AnnotationTypeDeclaration) ape.getTypeDeclaration("practiceproject.MyInterface");
    }

    public void process() {
        Collection<Declaration> decls = ape.getDeclarationsAnnotatedWith(atd);
        for (Declaration dec : decls) {
            processDeclaration(dec);
        }
    }

    private void processDeclaration(Declaration d) {
        Collection<AnnotationMirror> ams = d.getAnnotationMirrors();
        for (AnnotationMirror am : ams) {
            if (am.getAnnotationType().getDeclaration().equals(atd)) {
                Map<AnnotationTypeElementDeclaration, AnnotationValue> values = am.getElementValues();
                int offset = 0;
                int last = 100;
                for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> entry : values.entrySet()) {
                    AnnotationTypeElementDeclaration ated = entry.getKey();
                    AnnotationValue v = entry.getValue();
                    String name = ated.getSimpleName();
                    if (name.equals("offset")) {
                        offset = ((Integer) v.getValue()).intValue();
                    } else if (name.equals("last")) {
                        last = ((Integer) v.getValue()).intValue();
                    }
                }
                //find the sum
                System.err.println("Sum: " + ((last + 1 - offset) / 2) * (2 * offset + (last - offset)));
            }
        }
    }
}

然后我们创建一个源文件。简单的类使用 MyInterface 注释:

 @MyInterface(offset = 1, last = 1000)
public class Main {

    @MyInterface
    void doNothing() {
        System.out.println("Doing nothing");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Main m = new Main();
        m.doNothing();
        MyInterface my = (MyInterface) m.getClass().getAnnotation(MyInterface.class);
        System.out.println("offset: " + my.offset());
        System.out.println("Last: " + my.last());
    }
}

注解处理器被编译成一个jar文件,然后使用apt工具编译源文件,如下所示:

apt -cp "D:\Variance project\PracticeProject\dist\practiceproject.jar" -factory practiceproject.annotprocess.MyInterfaceAnnotationProcessorFactory "D:\Variance project\PracticeProject2\src\practiceproject2\Main.java"
该项目的输出结果为:
Called supportedAnnotationTypes...........................
Called getProcessorFor................
Sum: 5000
Sum: 500500

9

这是一个在VC++ 2010下运行的实现。由于模板递归500多次时编译器会发出警告,因此我将计算分为了3个阶段。

template<int t_startVal, int t_baseVal = 0, int t_result = 0>
struct SumT
{
    enum { result = SumT<t_startVal - 1, t_baseVal, t_baseVal + t_result +
        t_startVal>::result };
};

template<int t_baseVal, int t_result>
struct SumT<0, t_baseVal, t_result>
{
    enum { result = t_result };
};

template<int output_value>
struct Dump
{
    enum { value = output_value };
    int bad_array[0];
};

enum
{
    value1 = SumT<400>::result,                // [1,400]
    value2 = SumT<400, 400, value1>::result,   // [401, 800]
    value3 = SumT<200, 800, value2>::result    // [801, 1000]
};

Dump<value3> dump;

当您编译此代码时,编译器应该会输出类似以下内容的结果:
1>warning C4200: nonstandard extension used : zero-sized array in struct/union
1>          Cannot generate copy-ctor or copy-assignment operator when UDT contains a 
zero-sized array
1>          templatedrivensum.cpp(33) : see reference to class template 
instantiation 'Dump<output_value>' being compiled
1>          with
1>          [
1>              output_value=500500
1>          ]

非常好的想法,将其分解,我认为我会以某种方式将其整合到我的答案中。 +1 :) - Xeo

9

我觉得有义务提供这段 C 代码,因为还没有人做过:

#include <stdio.h>
int main() {
   int x = 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+
           21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+
           41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+
           61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+
           81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100+     
           101+102+103+104+105+106+107+108+109+110+111+112+113+114+115+116+117+118+119+120+
           121+122+123+124+125+126+127+128+129+130+131+132+133+134+135+136+137+138+139+140+
           141+142+143+144+145+146+147+148+149+150+151+152+153+154+155+156+157+158+159+160+
           161+162+163+164+165+166+167+168+169+170+171+172+173+174+175+176+177+178+179+180+
           181+182+183+184+185+186+187+188+189+190+191+192+193+194+195+196+197+198+199+200+
           201+202+203+204+205+206+207+208+209+210+211+212+213+214+215+216+217+218+219+220+
           221+222+223+224+225+226+227+228+229+230+231+232+233+234+235+236+237+238+239+240+
           241+242+243+244+245+246+247+248+249+250+251+252+253+254+255+256+257+258+259+260+
           261+262+263+264+265+266+267+268+269+270+271+272+273+274+275+276+277+278+279+280+
           281+282+283+284+285+286+287+288+289+290+291+292+293+294+295+296+297+298+299+300+
           301+302+303+304+305+306+307+308+309+310+311+312+313+314+315+316+317+318+319+320+
           321+322+323+324+325+326+327+328+329+330+331+332+333+334+335+336+337+338+339+340+
           341+342+343+344+345+346+347+348+349+350+351+352+353+354+355+356+357+358+359+360+
           361+362+363+364+365+366+367+368+369+370+371+372+373+374+375+376+377+378+379+380+
           381+382+383+384+385+386+387+388+389+390+391+392+393+394+395+396+397+398+399+400+
           401+402+403+404+405+406+407+408+409+410+411+412+413+414+415+416+417+418+419+420+
           421+422+423+424+425+426+427+428+429+430+431+432+433+434+435+436+437+438+439+440+
           441+442+443+444+445+446+447+448+449+450+451+452+453+454+455+456+457+458+459+460+
           461+462+463+464+465+466+467+468+469+470+471+472+473+474+475+476+477+478+479+480+
           481+482+483+484+485+486+487+488+489+490+491+492+493+494+495+496+497+498+499+500+
           501+502+503+504+505+506+507+508+509+510+511+512+513+514+515+516+517+518+519+520+
           521+522+523+524+525+526+527+528+529+530+531+532+533+534+535+536+537+538+539+540+
           541+542+543+544+545+546+547+548+549+550+551+552+553+554+555+556+557+558+559+560+
           561+562+563+564+565+566+567+568+569+570+571+572+573+574+575+576+577+578+579+580+
           581+582+583+584+585+586+587+588+589+590+591+592+593+594+595+596+597+598+599+600+
           601+602+603+604+605+606+607+608+609+610+611+612+613+614+615+616+617+618+619+620+
           621+622+623+624+625+626+627+628+629+630+631+632+633+634+635+636+637+638+639+640+
           641+642+643+644+645+646+647+648+649+650+651+652+653+654+655+656+657+658+659+660+
           661+662+663+664+665+666+667+668+669+670+671+672+673+674+675+676+677+678+679+680+
           681+682+683+684+685+686+687+688+689+690+691+692+693+694+695+696+697+698+699+700+
           701+702+703+704+705+706+707+708+709+710+711+712+713+714+715+716+717+718+719+720+
           721+722+723+724+725+726+727+728+729+730+731+732+733+734+735+736+737+738+739+740+
           741+742+743+744+745+746+747+748+749+750+751+752+753+754+755+756+757+758+759+760+
           761+762+763+764+765+766+767+768+769+770+771+772+773+774+775+776+777+778+779+780+
           781+782+783+784+785+786+787+788+789+790+791+792+793+794+795+796+797+798+799+800+
           801+802+803+804+805+806+807+808+809+810+811+812+813+814+815+816+817+818+819+820+
           821+822+823+824+825+826+827+828+829+830+831+832+833+834+835+836+837+838+839+840+
           841+842+843+844+845+846+847+848+849+850+851+852+853+854+855+856+857+858+859+860+
           861+862+863+864+865+866+867+868+869+870+871+872+873+874+875+876+877+878+879+880+
           881+882+883+884+885+886+887+888+889+890+891+892+893+894+895+896+897+898+899+900+
           901+902+903+904+905+906+907+908+909+910+911+912+913+914+915+916+917+918+919+920+
           921+922+923+924+925+926+927+928+929+930+931+932+933+934+935+936+937+938+939+940+
           941+942+943+944+945+946+947+948+949+950+951+952+953+954+955+956+957+958+959+960+
           961+962+963+964+965+966+967+968+969+970+971+972+973+974+975+976+977+978+979+980+
           981+982+983+984+985+986+987+988+989+990+991+992+993+994+995+996+997+998+999+1000;
  printf("%d\n", x);
}

我只需要查看汇编代码就能找到答案!

gcc -S compile_sum.c;
grep "\$[0-9]*, *-4" compile_sum.s

And I see:

movl    $500500, -4(%rbp)

特定实现的功能,而不是C语言。 - Puppy
5
你知道有多少个不是C的“特定实现”的C编译器? - Carl Walsh
@Puppy:如果x是全局变量,编译器(或多或少)需要在编译时评估表达式。 ISO C不允许在全局变量中使用运行时变量初始化程序。 当然,特定的实现可以发出类似于构造函数的静态初始化函数的调用来计算它并存储它。 但是,ISO C确实允许您将编译时常量用作数组大小(例如,在结构定义中或作为另一个全局变量中使用int y [x];),因此任何假设的悲观实现仍必须支持该功能。 - Peter Cordes

7

在 Carl Walsh 的回答基础上进行扩展,实际上可以在编译期间打印结果:

#define VALUE (1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+\
21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+\
41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+\
61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+\
81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100+\
101+102+103+104+105+106+107+108+109+110+111+112+113+114+115+116+117+118+119+120+\
121+122+123+124+125+126+127+128+129+130+131+132+133+134+135+136+137+138+139+140+\
141+142+143+144+145+146+147+148+149+150+151+152+153+154+155+156+157+158+159+160+\
161+162+163+164+165+166+167+168+169+170+171+172+173+174+175+176+177+178+179+180+\
181+182+183+184+185+186+187+188+189+190+191+192+193+194+195+196+197+198+199+200+\
201+202+203+204+205+206+207+208+209+210+211+212+213+214+215+216+217+218+219+220+\
221+222+223+224+225+226+227+228+229+230+231+232+233+234+235+236+237+238+239+240+\
241+242+243+244+245+246+247+248+249+250+251+252+253+254+255+256+257+258+259+260+\
261+262+263+264+265+266+267+268+269+270+271+272+273+274+275+276+277+278+279+280+\
281+282+283+284+285+286+287+288+289+290+291+292+293+294+295+296+297+298+299+300+\
301+302+303+304+305+306+307+308+309+310+311+312+313+314+315+316+317+318+319+320+\
321+322+323+324+325+326+327+328+329+330+331+332+333+334+335+336+337+338+339+340+\
341+342+343+344+345+346+347+348+349+350+351+352+353+354+355+356+357+358+359+360+\
361+362+363+364+365+366+367+368+369+370+371+372+373+374+375+376+377+378+379+380+\
381+382+383+384+385+386+387+388+389+390+391+392+393+394+395+396+397+398+399+400+\
401+402+403+404+405+406+407+408+409+410+411+412+413+414+415+416+417+418+419+420+\
421+422+423+424+425+426+427+428+429+430+431+432+433+434+435+436+437+438+439+440+\
441+442+443+444+445+446+447+448+449+450+451+452+453+454+455+456+457+458+459+460+\
461+462+463+464+465+466+467+468+469+470+471+472+473+474+475+476+477+478+479+480+\
481+482+483+484+485+486+487+488+489+490+491+492+493+494+495+496+497+498+499+500+\
501+502+503+504+505+506+507+508+509+510+511+512+513+514+515+516+517+518+519+520+\
521+522+523+524+525+526+527+528+529+530+531+532+533+534+535+536+537+538+539+540+\
541+542+543+544+545+546+547+548+549+550+551+552+553+554+555+556+557+558+559+560+\
561+562+563+564+565+566+567+568+569+570+571+572+573+574+575+576+577+578+579+580+\
581+582+583+584+585+586+587+588+589+590+591+592+593+594+595+596+597+598+599+600+\
601+602+603+604+605+606+607+608+609+610+611+612+613+614+615+616+617+618+619+620+\
621+622+623+624+625+626+627+628+629+630+631+632+633+634+635+636+637+638+639+640+\
641+642+643+644+645+646+647+648+649+650+651+652+653+654+655+656+657+658+659+660+\
661+662+663+664+665+666+667+668+669+670+671+672+673+674+675+676+677+678+679+680+\
681+682+683+684+685+686+687+688+689+690+691+692+693+694+695+696+697+698+699+700+\
701+702+703+704+705+706+707+708+709+710+711+712+713+714+715+716+717+718+719+720+\
721+722+723+724+725+726+727+728+729+730+731+732+733+734+735+736+737+738+739+740+\
741+742+743+744+745+746+747+748+749+750+751+752+753+754+755+756+757+758+759+760+\
761+762+763+764+765+766+767+768+769+770+771+772+773+774+775+776+777+778+779+780+\
781+782+783+784+785+786+787+788+789+790+791+792+793+794+795+796+797+798+799+800+\
801+802+803+804+805+806+807+808+809+810+811+812+813+814+815+816+817+818+819+820+\
821+822+823+824+825+826+827+828+829+830+831+832+833+834+835+836+837+838+839+840+\
841+842+843+844+845+846+847+848+849+850+851+852+853+854+855+856+857+858+859+860+\
861+862+863+864+865+866+867+868+869+870+871+872+873+874+875+876+877+878+879+880+\
881+882+883+884+885+886+887+888+889+890+891+892+893+894+895+896+897+898+899+900+\
901+902+903+904+905+906+907+908+909+910+911+912+913+914+915+916+917+918+919+920+\
921+922+923+924+925+926+927+928+929+930+931+932+933+934+935+936+937+938+939+940+\
941+942+943+944+945+946+947+948+949+950+951+952+953+954+955+956+957+958+959+960+\
961+962+963+964+965+966+967+968+969+970+971+972+973+974+975+976+977+978+979+980+\
981+982+983+984+985+986+987+988+989+990+991+992+993+994+995+996+997+998+999+1000)

char tab[VALUE];

int main()
{
    tab = 5;
}

gcc的输出:

test.c: In function 'main':
test.c:56:9: error: incompatible types when assigning to type 'char[500500]' fro
m type 'int'

2
你可以使用(并且很大程度上滥用)C++宏/模板来进行元编程,但据我所知Java不允许这样的事情。metaprogramming

2
并不是对问题的真正回答。 - Ikke
我认为你是正确的。在Java中,您不能使用相同的模板递归技巧,因为通用类参数不能是值 - 它必须是一个类。 - Eyal Schneider
C#编译器的泛型特性允许您进行一些编译时计算。请参阅Eric Lippert的帖子 - Allon Guralnek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接