Tạo một chương trình C mất nhiều thời gian nhất để biên dịch trong gcc


27

Tạo một chương trình C ngắn cần một thời gian dài vô lý để biên dịch với gcc. Các mục sẽ được tính bằng cách tính thời gian biên dịch sau đó trừ đi thời gian biên dịch của chương trình tham chiếu.

Quy tắc

  • Bất kỳ tính năng ngôn ngữ C hoặc phần mở rộng gcc
  • gcc 4.2.1

1
Đã thay đổi cách gắn thẻ vì [code-golf] có nghĩa rõ ràng là "mã ngắn bằng số (đột quỵ) đếm".
dmckee

6
Chia cho số lượng ký tự không có nhiều ý nghĩa, bởi vì bất kỳ cách tiếp cận hợp lý nào cho thử thách này tất nhiên sẽ có độ phức tạp thời gian biên dịch lớn hơn O ( n ), tức là điểm của bất kỳ giải pháp nào cũng có thể tăng lên một cách tầm thường chỉ bằng cách thực hiện lâu hơn một chút, có lẽ sẽ luôn luôn có thể theo một cách rõ ràng.
đã ngừng quay ngược chiều

Câu trả lời:


13
#define a "xxxxxxxxxxx"
#define b a a a a a a a
#define c b b b b b b b
#define d c c c c c c c
#define e d d d d d d d
#define f e e e e e e e
#define g f f f f f f f
#define h g g g g g g g
#define i h h h h h h h
#define j i i i i i i i
z=j;

Không biên dịch trên máy của tôi
FUZxxl

19
Tối thiểu, dòng cuối cùng cần được thay đổi thành một cái gì đó giống như main(){char*z=j;}làm cho đây là một chương trình c hợp lệ.
dmckee

2
VS2012 của tôi ra khỏi không gian heap. Tôi đoán /Zmsẽ sửa nó
rev

13

Cả câu trả lời của Charliecâu trả lời trước đó của tôi đều hoạt động theo nguyên tắc cho phép bộ xử lý trước viết rất nhiều mã, nhưng họ chủ yếu thực hiện chính bộ xử lý trước, lexer (ý tưởng tốt là bước này thường chậm) và trình phân tích cú pháp. Mine cũng cố gắng thực hiện các bước tối ưu hóa và tạo mã, nhưng rõ ràng nó không đạt được nhiều ở đó.

Suy nghĩ về cách một trình biên dịch c điển hình hoạt động, tôi nhận ra rằng chúng ta sẽ không cung cấp mã biểu tượng liên quan đến bảng biểu tượng. Mục này là một nỗ lực để khắc phục điều đó. Nó được cho là gợi nhớ đến việc định hướng đối tượng cơ bản trong triển khai c, nhưng không làm gì thú vị: sử dụng kỹ thuật mở rộng tiền xử lý để khai báo và tầm thường (và không chính xác) khởi tạo một loạt các đối tượng. Các đối tượng sử dụng các loại phức tạp, trên nhiều cấp độ phạm vi, tạo bóng cho nhau ở các mức loại bỏ khác nhau. Nó nên cung cấp cho bảng biểu tượng một công việc thực sự ra.

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
// Exercise the symbol table mechanism of the compiler in an effort to
// take a unreasonable about of time compiling

#define PTR(T) T*
#define CONST(T) T const
#define FUNC(NAME,RTYPE,ARG) RTYPE NAME(ARG)
#define FPTR(NAME,RTYPE,ARG) FUNC((*NAME),RTYPE,ARG)

// Forward decalration of repeated OO method pointers
typedef void* (*cctor_ptr)(void*this, void*that, ...);
typedef void* (*dtor_ptr)(void*this);

// Assumes three var-args: sizeof(payload type), cctor, dtor
void* default_ctor(void*this, ...){
  // Pull in variadac bits
  va_list list;
  va_start(list,this);
  int size=va_arg(list,int);
  cctor_ptr cctor=va_arg(list,cctor_ptr);
  dtor_ptr dtor=va_arg(list,dtor_ptr);
  va_end(list);
  // process
  if (!this) this = malloc(size);
  if (this) {
    memset(this,size,0);
    /* various dodges to install the cctor and dtor in the write places */
  }
  return this;
}
// Copies the payload from that to this; 
void* default_cctor(void*restrict this, void* restrict that, ...){
  // Pull in variadac bits
  va_list list;
  va_start(list,that);
  int size=va_arg(list,int);
  cctor_ptr cctor=va_arg(list,cctor_ptr);
  dtor_ptr dtor=va_arg(list,dtor_ptr);
  va_end(list);
  // process
  if (!this) this = malloc(size);
  if (this) {
    memcpy(this,that,size);
    /* various dodges to install the cctor and dtor in the write places */
  }
  return this;
}
// Assumes that his was allocated with malloc, does not use varargs
void* default_dtor(void*this, ...){
  free(this); 
  return NULL;
};

#define DECLARE_STRUCT(N) struct S##N##_s
#define TYPEDEF_ACCESSOR(N,T) typedef FPTR(f##N##_ptr,CONST(PTR(T)),PTR(CONST(struct S##N##_s)))
#define TYPEDEF_STRUCT(N,T) typedef struct S##N##_s {PTR(T)p; cctor_ptr cctor; dtor_ptr dtor; f##N##_ptr f##N;} S##N
#define OO_STRUCT(N,T) DECLARE_STRUCT(N); TYPEDEF_ACCESSOR(N,T); TYPEDEF_STRUCT(N,T)

OO_STRUCT(1,char);
OO_STRUCT(2,int);
OO_STRUCT(3,double*);
OO_STRUCT(4,S3);
OO_STRUCT(5,S4);
OO_STRUCT(6,S5);
OO_STRUCT(7,S6);
OO_STRUCT(8,S7);

#define SUBSCOPE(A) { \
    S1*A##1=default_ctor(NULL,sizeof(char),default_cctor,default_dtor); \
    S2 A##2; default_ctor(&A##2,sizeof(int),default_cctor,default_dtor); \
    S2*A##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
    S8 A##5; default_ctor(&A##5,sizeof(S4),default_cctor,default_dtor); \
    S6 A##6; default_ctor(&A##6,sizeof(S5),default_cctor,default_dtor); \
    S8*A##8=default_ctor(NULL,sizeof(S7),default_cctor,default_dtor); \
  }
#define SUBSCOPE2(A,B)  { \
    S2*B##5=default_ctor(NULL,sizeof(S4),default_cctor,default_dtor); \
    S4 A##7; default_ctor(&A##7,sizeof(S6),default_cctor,default_dtor); \
    SUBSCOPE(A) SUBSCOPE(B);                 \
  }
#define SUBSCOPE6(A,B,C)  { \
    S2*A##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
    S2 B##2; default_ctor(&B##2,sizeof(int),default_cctor,default_dtor); \
    S4*C##4=NULL;                           \
    SUBSCOPE2(A,C) SUBSCOPE2(B,C) SUBSCOPE2(A,B); \
  }
#define SUBSCOPE24(A,B,C,D) { \
    S1*D##1=default_ctor(NULL,sizeof(char),default_cctor,default_dtor); \
    S2 C##2; default_ctor(&C##2,sizeof(int),default_cctor,default_dtor); \
    S2*B##3=default_ctor(NULL,sizeof(double*),default_cctor,default_dtor); \
    S4 A##4; default_ctor(&A##4,sizeof(S3),default_cctor,default_dtor); \
    SUBSCOPE6(A,B,C) SUBSCOPE6(A,B,D) SUBSCOPE6(A,C,D) SUBSCOPE6(B,C,D); \
  }
#define SUBSCOPE120(A,B,C,D,E) { \
    S5*A##5=default_ctor(NULL,sizeof(S4),default_cctor,default_dtor); \
    S6*A##6=default_ctor(NULL,sizeof(S5),default_cctor,default_dtor); \
    S8 A##8; default_ctor(&A##8,sizeof(S7),default_cctor,default_dtor); \
    SUBSCOPE24(A,B,C,D) SUBSCOPE24(A,B,C,E) SUBSCOPE24(A,B,D,E); \
    SUBSCOPE24(A,C,D,E) SUBSCOPE24(B,C,D,E); \
  }
#define SUBSCOPE720(A,B,C,D,E,F) { \
    S5 A##5; default_ctor(&A##5,sizeof(S4),default_cctor,default_dtor); \
    S6 A##6; default_ctor(&A##6,sizeof(S5),default_cctor,default_dtor); \
    S8*A##8=default_ctor(NULL,sizeof(S7),default_cctor,default_dtor); \
    SUBSCOPE120(A,B,C,D,E) SUBSCOPE120(A,B,C,D,F) SUBSCOPE120(A,B,C,E,F); \
    SUBSCOPE120(A,B,D,E,F) SUBSCOPE120(A,C,D,E,F) SUBSCOPE120(B,C,D,E,F); \
  }

int main(){
  S4 s4;
  SUBSCOPE720(A,B,C,D,E,F)
}

Thời gian biên dịch trên máy của tôi vượt quá 4 giây -O3và hơn 1 giây không được tối ưu hóa.


Rõ ràng bước tiếp theo sẽ là hoàn thành việc triển khai OO cho các lớp BCD và thực hiện lại các phép tính pi bằng cách sử dụng nó để tôi có được cả hai hiệu ứng chạy mạnh.


12

Đây là một đoạn ngắn của chủ đề mở rộng tiền xử lý theo cấp số nhân, điều thực hiện một điều thú vị tối thiểu: tính hai phép tính gần đúng với pi bằng các phương thức chuỗi và so sánh với cả giá trị trong math.h và câu thần chú thông thường.

Ung dung.

#include <math.h>
#include <stdio.h>

// Some random bits we'll need
#define MINUSONODD(n) (n%2?-1:+1)
#define TWON(n) (2*(n))
#define NPLUSONE(n) ((n)+1)
#define TWONPLUSONE(n) NPLUSONE(TWON(n))
#define FACT(n) (tgamma(NPLUSONE(n)))

// The Euler series
//                           2^(2n) * (n!)^2      z^(2n+1)
// atan(z) = \sum_n=0^\infty --------------- * ---------------
//                               (2n+1)!       (1 + z^2)^(n+1)
#define TERMEULER(n,z) (pow(2,TWON(n))*                 \
            FACT(n)*FACT(n)*                \
            pow((z),TWONPLUSONE(n))/            \
            FACT(TWONPLUSONE(n)) /              \
            pow((1+z*z),NPLUSONE(n)) )

// The naive version
//                           (-1)^n * z^(2n+1)
// atan(z) = \sum_n=0^\infty -----------------
//                                2n + 1
#define TERMNAIVE(n,z) (MINUSONODD(n)*pow(z,TWONPLUSONE(n))/TWONPLUSONE(n))


// Define a set of bifruncations of the sum
#define N2TERMS(n,z,ALG)  (TERM##ALG(TWON(n),(z)) + TERM##ALG(TWONPLUSONE(n),(z)))
#define N4TERMS(n,z,ALG)  (N2TERMS(TWON(n),(z),ALG)+N2TERMS(TWONPLUSONE(n),(z),ALG))
#define N8TERMS(n,z,ALG)  (N4TERMS(TWON(n),(z),ALG)+N4TERMS(TWONPLUSONE(n),(z),ALG))
#define N16TERMS(n,z,ALG) (N8TERMS(TWON(n),(z),ALG)+N8TERMS(TWONPLUSONE(n),(z),ALG))
#define N32TERMS(n,z,ALG) (N16TERMS(TWON(n),(z),ALG)+N16TERMS(TWONPLUSONE(n),(z),ALG))

// Sum the fist 32*2+16 = 80 terms of a series...
#define PARTIALSUM(z,ALG) N32TERMS(0,(z),ALG)+N32TERMS(1,(z),ALG)+N16TERMS(4,(z),ALG)


int main(void){
  const double PI_TRAD = 4.0L * atan(1.0);
  const double PI_NAIVE = 4.0L * PARTIALSUM(0.999999L,NAIVE);
  const double PI_EULER = 4.0L * PARTIALSUM(0.999999L,EULER);
  printf("pi (math.h) = %10.8f\n",M_PI);
  printf("pi (trad.)  = %10.8f\n",PI_TRAD);
  printf("pi (NAIVE)  = %10.8f\n",PI_NAIVE);
  printf("pi (EULER)  = %10.8f\n",PI_EULER);
}

Giả sử rằng bạn đang sử dụng gccglibccó thể hoặc không thể làm việc với các sắp xếp khác. Phải mất khoảng 1,0-1,1 giây thời gian của bộ xử lý (được đánh giá bằng time (1)) để biên dịch với-03 1 trên MacBook Intel Core 2 Duo 2,4 GHz của tôi. Một trình biên dịch mặc định mất khoảng 0,4 giây thời gian xử lý.

Than ôi, tôi không thể đánh giá gcc pow hoặc tgammatại thời điểm biên dịch, điều này thực sự có ích.

Khi bạn chạy nó, đầu ra là:

pi (math.h) = 3.14159265
pi (trad.)  = 3.14159265
pi (NAIVE)  = 3.11503599
pi (EULER)  = 3.14159065

trong đó cho thấy các chuỗi ngây thơ hội tụ chậm như thế nào.


1 Để có được càng nhiều lần loại bỏ và loại bỏ biểu thức phụ càng tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.