सी में गोल्फ के लिए युक्तियाँ


137

सी में गोल्फिंग के लिए आपके पास क्या सामान्य सुझाव हैं? मैं उन विचारों की तलाश कर रहा हूं जो सामान्य रूप से सी में गोल्फ की समस्याओं को लागू करने के लिए लागू हो सकते हैं जो कम से कम कुछ सी के लिए विशिष्ट हैं (उदाहरण के लिए "टिप्पणियां हटाएं" एक उत्तर नहीं है)। कृपया प्रति उत्तर एक टिप पोस्ट करें। इसके अलावा, कृपया यह भी शामिल करें कि क्या आपकी टिप C89 और / या C99 पर लागू होती है और यदि यह केवल कुछ कंपाइलर पर काम करती है।


8
मुझे लगता है कि सबसे बड़ा एकल-वाक्य संकेत है: IOCCC को प्रस्तुत किए गए विजेता कोड पढ़ें।
vsz

जवाबों:


107

पूर्णांक के बीच असमानता की जांच करने के लिए बिटवाइर XOR का उपयोग करें:

if(a^b)के बजाय if(a!=b)1 चरित्र बचाता है।


73
a-bआपको वही प्रभाव देता है।
ugoren

22
इसी तरह आप a*bइसके बजाय का उपयोग कर सकते हैं a&&b(अलग-अलग प्राथमिकता है, बुरा हो सकता है या नहीं)। यदि आप जानते हैं कि a / = -b (जैसे कि वे अहस्ताक्षरित हैं) तो a||b==a+b
खोलें

3
बेहतर अभी तक इसे एल्विस ऑपरेटर के साथ मिलाएं ?:(यदि के बजाय): केवल अलग करने के लिए कुछ करने की छूट के लिए: a^b?_diff_:;
ओलिवियर दुलैक

1
@OlivierDulac क्या कोई कंपाइलर है जो झूठी शाखा होने पर एक खाली टर्नरी को स्वीकार करता है?
जोनाथन फ्रीच

1
@OlivierDulac आप देख सकते हैं। जो मैं जानता हूँ से, जीसीसी एक है ?:ऑपरेटर जो करने के लिए बस बराबर हैa ? a : b
क्रोमियम

75
  • दुर्व्यवहार mainकी तर्क सूची को एक या अधिक पूर्णांक चर घोषित करने के लिए:

    main(a){for(;++a<28;)putchar(95+a);}
    

    ( प्रोग्रामिंग भाषाओं में वर्णमाला का उत्तर )

    यह समाधान इस तथ्य का भी दुरुपयोग करता है कि a(उर्फ argc) के रूप में शुरू होता है 1, बशर्ते कार्यक्रम को बिना किसी तर्क के कहा जाता है।

  • चीजों को शून्य करने के लिए वैश्विक चर का उपयोग करें:

    t[52],i;main(c){for(;i<52;)(c=getchar())<11?i+=26:t[i+c-97]++;
    for(i=27;--i&&t[i-1]==t[i+25];);puts(i?"false":"true");}
    

    ( एनाग्राम कोड गोल्फ का जवाब ! )


62

अल्पविराम ऑपरेटर को ब्रेसिज़ से बचने के दौरान एक ही ब्लॉक में कई भाव निष्पादित करने के लिए इस्तेमाल किया जा सकता है:

main(){                                                                                     

int i = 0;                                                                                  
int j = 1;                                                                                  
if(1)                                                                                       
    i=j,j+=1,printf("%d %d\n",i,j); // multiple statements are all executed                                                  
else                                                                                        
    printf("failed\n");                                                                     

}

आउटपुट: 1 2


बयानों में से एक होने पर काम नहीं करता है break
मैक्सिम मिखायलोव

9
@MaxLawnboy क्योंकि breakएक बयान है, और यह जवाब अभिव्यक्ति के बारे में बात कर रहा है।
नेद्देज्जकोब

59

भयावह फ़ंक्शन-तर्क प्रकार की घोषणाओं से बचें

यदि आप एक ऐसा समारोह घोषित कर रहे हैं, जहां सभी पांच तर्क हैं int, तो जीवन अच्छा है। आप बस लिख सकते हैं

f(a,b,c,d,e){

लेकिन मान लें कि dएक char, या यहां तक ​​कि एक होने की जरूरत है int*। फिर तुम खराब हो! यदि एक पैरामीटर एक प्रकार से पहले है, तो उन सभी को होना चाहिए:

f(int a,int b,int c,int*d,int e){

लेकिन रुकें! बेकार पात्रों के इस विनाशकारी विस्फोट के चारों ओर एक रास्ता है। यह इस प्रकार चलता है:

f(a,b,c,d,e) int *d; {

यहां तक ​​कि mainअगर आप कमांड-लाइन तर्कों का उपयोग करने की आवश्यकता है, तो यह एक मानक घोषणा पर भी बचाता है:

main(c,v)char**v;{

दो बाइट्स से छोटा है

main(int c,char**v){

मुझे यह जानकर आश्चर्य हुआ, क्योंकि मैंने अब तक पीपीसीजी पर इसका सामना नहीं किया है।


6
पृथ्वी पर वह काम क्यों करता है ??
नथानिएल

30
जाहिरा तौर पर इसे K & R स्टाइल कहा जाता है और यह ANSI C को एक दशक पहले पसंद करता है।
डेनिस

ध्यान दें कि K & R फीचर्स और नए का उपयोग करें (कहते हैं '99) एक साथ nay या संभव नहीं है। आपके कंपाइलर पर निर्भर करता है।
dmckee

5
@ डमकी सही है। C99 अंतर्निहित int की अनुमति नहीं देता है, इसलिए आपको उपयोग करना होगा -std=gnu99और अब आप पोर्टेबल नहीं हैं। Clc-Speak में, आप "C" कोड प्रति se भी नहीं लिख रहे हैं, लेकिन "Gnu99-C"। 'राउंड यहाँ हम ज्यादातर उस पर ध्यान नहीं देते हैं, लेकिन इसका उल्लेख करना अच्छा है यदि आप कोड-पोस्ट करते हैं जो संकलक-विशिष्ट है। कभी कभी लोगों को वास्तव में है डाउनलोड करने और हमारा इन कार्यक्रमों पर अमल। :)
लूसर डॉग

@luserdroog: आप -std=c89उस पुराने मानक के अनुसार अपने कोड को संकलित करने के लिए gcc या क्लैंग को बताने के लिए उपयोग कर सकते हैं , जो केवल एक चेतावनी के साथ निहित int की अनुमति देता है।
पीटर कॉर्ड्स

37

इसके बजाय> = और <= आप केवल पूर्णांक विभाजन (/) का उपयोग कर सकते हैं जब तुलनात्मक मान शून्य से ऊपर होते हैं, जो एक वर्ण को बचाता है। उदाहरण के लिए:

putchar(c/32&&126/c?c:46); //Prints the character, but if it is unprintable print "."

जो निश्चित रूप से अभी भी संकोचन योग्य है, उदाहरण के लिए बस> और ^ (कुछ मामलों में लेखन && या || से बचने का एक स्मार्ट तरीका) का उपयोग करना।

putchar(c>31^c>126?c:46);

पूर्णांक विभाजन चाल उदाहरण के लिए उपयोगी है यह तय करने के लिए कि क्या संख्या 100 से कम है, क्योंकि यह एक चरित्र को बचाता है:

a<100 vs 99/a

यह उन मामलों में भी अच्छा है जब उच्च वरीयता की आवश्यकता होती है।


आप लिख सकते हैंputchar(c>31&c<127?c:46);
जिन एक्स

37

कुछ संकलक, जैसे कि जीसीसी, आपको मूल #includes, परम, और रिटर्न प्रकारों को छोड़ने की अनुमति देते हैं main

निम्नलिखित एक मान्य C89 और C99 प्रोग्राम है जो जीसीसी के साथ (चेतावनी के साथ) संकलित करता है:

main(i) { printf("%d", i); }

ध्यान दें कि #includestdio.h के लिए अनुपलब्ध है, के लिए वापसी प्रकार mainगायब है, और प्रकार के लिए घोषणा iयाद आ रही है।


17
तकनीकी रूप से यह मानकों के अनुसार मान्य नहीं है क्योंकि मुख्य शून्य या दो मापदंडों को स्वीकार करता है, एक को नहीं। ऐसा नहीं है कि किसी को भी कोड गोल्फ में परवाह है।
कोनराड बोरोस्की

printf()प्रोटोटाइप के बिना कॉलिंग (या कोई भी वैरिएडिक फ़ंक्शन) अपरिभाषित व्यवहार का कारण बनता है । जीसीसी डिफ़ॉल्ट रूप से मानक सी का संकलन नहीं करता है। यदि आप C89 मोड ( gcc -ansi -pedantic) या C99 मोड ( gcc -std=c99 -pedantic) में gcc का आह्वान करते हैं , तो आपको कम से कम बाद की स्थिति में काफी शिकायतें मिलेंगी।
निंग एन्स्ट्रॉसम

@ निस्संगस्ट्रोम: मुख्यधारा के सी कार्यान्वयन पर कॉलिंग कन्वेंशनों को प्रोटोटाइप के बिना वैरेडिक फ़ंक्शन को कॉल करना सुरक्षित है। इसलिए अधिकांश सी कार्यान्वयन व्यवहार को परिभाषित करते हैं।
पीटर कॉर्डेस

29

टर्नरी सशर्त ऑपरेटर ?:को अक्सर सरल के लिए एक स्टैंड के रूप में इस्तेमाल किया जा सकता है if- elseकाफी बचत पर बयान।

सी ++ के विपरीत ऑपरेटर ऑपरेटर को औपचारिक रूप से एक उत्तोलन नहीं देता है , लेकिन कुछ संकलक (विशेष रूप से जीसीसी) आपको इसके साथ दूर होने देंगे, जो एक अच्छा बोनस है।


जोड़: यदि आपको केवल एक की जरूरत है, लेकिन एक और नहीं तो फिर भी टर्नरी उपयोगी हो सकती है।
केसी

9
&&और ||इसका उपयोग भी किया जा सकता है: if(x==3)f()आपके सुझाव के साथ बन जाता है x==3?f():0, और इसमें और सुधार किया जा सकता है x==3&&f()। लेकिन ऑपरेटर पूर्वता के साथ सावधान रहें - यदि f()इसके साथ प्रतिस्थापित किया जाता है y=1, तो &&समाधान को कोष्ठक के एक अतिरिक्त सेट की आवश्यकता होती है।
ugoren

1
मैं कभी नहीं महसूस किया है कि gcc की ?:पैदावार एक lvalue है। क्या मैं उत्पादन कोड में इसका उपयोग कर सकता हूं? lol
जेफ बर्देस

4
@ugoren: x==3&&f()आगे के लिए golfed किया जा सकता हैx^3||f()
fgrieu

@fgrieu, हाँ, हालाँकि यह वास्तव में यहाँ विषय नहीं है ( यह उत्तर यह सुझाव देता है)।
ugoren

27

http://graphics.stanford.edu/~seander/bithacks.html

बिट्स अच्छे हैं।

~-x = x - 1
-~x = x + 1

लेकिन विभिन्न पूर्वाग्रहों के साथ, और x को ++ और - की तरह नहीं बदलते हैं। इसके अलावा, आप वास्तव में विशिष्ट मामलों में इसका उपयोग कर सकते हैं: ~ 9 -10 से कम है।

if(!(x&y)) x | y == x ^ y == x + y
if(!(~x&y)) x ^ y == x - y

यह अधिक गूढ़ है, लेकिन मैंने इसका उपयोग करने के लिए अवसर दिया है। यदि आप शॉर्ट-सर्किटिंग के बारे में परवाह नहीं करते हैं

x*y == x && y
if(x!=-y) x+y == x || y

इसके अलावा:

if(x>0 && y>0) x/y == x>=y   

5
अंतिम टिप ( (x/y) == (x>=y)) वास्तव में उपयोगी है।
ugoren

24

लैम्ब्डा का प्रयोग करें (अप्राप्य)

के बजाय

f(int*a,int*b){return*a>*b?1:-1;}
...
qsort(a,b,4,f);

या (केवल जीसीसी)

qsort(a,b,4,({int L(int*a,int*b){a=*a>*b?1:-1;}L;}));

या (ब्लॉक समर्थन के साथ llvm)

qsort_b(a,b,4,^(const void*a,const void*b){return*(int*)a>*(int*)b?1:-1;});

कुछ ऐसा प्रयास करें

qsort(a,b,4,"\x8b\7+\6\xc3");

... जहां उद्धृत स्ट्रिंग में आपके "लैम्ब्डा" फ़ंक्शन की मशीन भाषा निर्देश (सभी प्लेटफॉर्म एबीआई आवश्यकताओं के अनुरूप) शामिल हैं।

यह ऐसे वातावरण में काम करता है जिसमें स्ट्रिंग स्थिरांक को निष्पादन योग्य चिह्नित किया जाता है। डिफ़ॉल्ट रूप से यह लिनक्स और ओएसएक्स में सही है लेकिन विंडोज में नहीं।

मूर्खतापूर्ण तरीके से अपने स्वयं के "लंबो" कार्यों को लिखने के लिए सी में फ़ंक्शन लिखना है, इसे संकलित करें, इसे कुछ इस तरह से निरीक्षण करें objdump -Dऔर संबंधित हेक्स कोड को एक स्ट्रिंग में कॉपी करें। उदाहरण के लिए,

int f(int*a, int*b){return *a-*b;}

... जब gcc -Os -cलिनक्स x86_64 लक्ष्य के लिए संकलित किया जाता है तो कुछ ऐसा उत्पन्न होता है

0:   8b 07                   mov    (%rdi),%eax
2:   2b 06                   sub    (%rsi),%eax
4:   c3                      retq

जीएनयू के सी.सी. goto :

आप इन "लंबो कार्यों" को सीधे कॉल कर सकते हैं लेकिन यदि आप जिस कोड को कॉल कर रहे हैं वह पैरामीटर नहीं लेता है और वापस नहीं जा रहा है, तो आप gotoकुछ बाइट्स को बचाने के लिए उपयोग कर सकते हैं । इसलिए इसके बजाय

((int(*)())L"ﻫ")();

या (यदि आपके पर्यावरण में अरबी ग्लिफ़ नहीं है)

((int(*)())L"\xfeeb")();

प्रयत्न, कोशिश

goto*&L"ﻫ";

या

goto*&L"\xfeeb";

इस उदाहरण में, eb fex86 मशीन भाषा है जैसे कुछfor(;;); और का एक सरल उदाहरण है जो पैरामीटर नहीं लेता है और वापस नहीं आने वाला है :-)

यह पता चला है gotoकि आप कॉल करने वाले माता-पिता के लिए कोड कर सकते हैं ।

#include<stdio.h>
int f(int a){
 if(!a)return 1;
 goto*&L"\xc3c031"; // return 0;
 return 2; // never gets here
}
int main(){
 printf("f(0)=%d f(1)=%d\n",f(0),f(1));
}

उपरोक्त उदाहरण (लिनक्स पर संकलित और चला सकता है) gcc -O ) स्टैक लेआउट के प्रति संवेदनशील है।

संपादित करें: आपके टूलकिन के आधार पर, आपको -zexecstackसंकलन ध्वज का उपयोग करना पड़ सकता है ।

यदि यह तुरंत स्पष्ट नहीं है, तो यह उत्तर मुख्य रूप से लोल के लिए लिखा गया था। मैं इसे पढ़ने से बेहतर या बदतर गोल्फिंग या प्रतिकूल मनोवैज्ञानिक परिणामों के लिए कोई ज़िम्मेदारी नहीं लेता।


2
मैंने अभी-अभी मानक से C फ़ंक्शन के कुछ हिस्सों को पढ़ने के लिए एक स्क्रिप्ट लिखी है और C lambda प्रिंट किया है। आपके उत्तर में ध्यान देने योग्य बात हो सकती है, शायद आपके लिए यह देखना अच्छा होगा क्योंकि आपने मुझे पहली बार ऐसा करना सिखाया था।
एमडी एक्सएफ

23

संकेत के बजाय कर्सर का उपयोग करें । brk()शुरुआत में रोड़ा और इसे बेस-पॉइंटर के रूप में उपयोग करें ।

char*m=brk();

फिर मेमोरी एक्सेस के लिए एक #define बनाएं।

#define M [m]

M*पूर्णांकों के लिए लागू पोस्टफ़िक्स बन जाता है । (पुराना एक [x] == x [a] ट्रिक।)

लेकिन, वहाँ अधिक है! तब आपके पास मैक्रो की तुलना में कम होने वाले फ़ंक्शंस में सूचक आर्ग और रिटर्न हो सकते हैं (विशेषकर यदि आप 'रिटर्न' संक्षिप्त करते हैं):

f(x){return x M;} //implicit ints, but they work like pointers
#define f(x) (x M)

एक पॉइंटर से एक कर्सर बनाने के लिए, आप बेस-पॉइंटर को घटाते हैं, एक ptrdiff_t की पैदावार करते हैं, जो एक इंट में काटता है, नुकसान yer biz है।

char *p = sbrk(sizeof(whatever)) - m;
strcpy(m+p, "hello world");

इस तकनीक का उपयोग मेरे जवाब में लावारिस लैम्ब्डा कैलकुलस के लिए एक दुभाषिया लिखने के लिए किया जाता है


21

चर के बजाय मापदंडों को परिभाषित करें।

f(x){int y=x+1;...}

f(x,y){y=x+1;...}

आपको वास्तव में दूसरे पैरामीटर को पारित करने की आवश्यकता नहीं है।

इसके अलावा, आप कोष्ठक को बचाने के लिए ऑपरेटर पूर्वता का उपयोग कर सकते हैं।
उदाहरण के लिए, (x+y)*2बन सकता है x+y<<1


या बस x+y*2, एक और चार की बचत।
ब्रैडन बेस्ट

4
@ B1KMusic, x+y*2ऑपरेटर पूर्वता के कारण समान नहीं है।
बदसूरत

राइट, लोल। यह x + (y * 2) होगा। मुझे x+y<<1उदाहरण पर तय किया गया था , यह मानते हुए कि इसका मूल्यांकन किया जा रहा है x+(y<<1), और *2इसके बजाय सुझाव दिया गया है । मुझे नहीं पता था कि बिटशिफ्ट ऑपरेशन का मूल्यांकन किया गया था(x+y)<<2
ब्रैडेन बेस्ट

20

चूंकि आमतौर पर EOF == -1, EOF के लिए जाँच करने के लिए बिटवाइज़ NOT ऑपरेटर का उपयोग करें: while(~(c=getchar()))या while(c=getchar()+1)हर स्थान पर c का मान संशोधित करें


1
मैं सी को अच्छी तरह से नहीं जानता, लेकिन while(1+c=getchar())काम नहीं करेगा ?
atı

6
@ hası higheruʎs नहीं। इसके अलावा ऑपरेटर के +पास असाइनमेंट ऑपरेटर की तुलना में अधिक पूर्वता है =, इसलिए 1+c=getchar()इसके बराबर है (1+c)=getchar(), जो संकलित नहीं करता है क्योंकि (1+c)यह एक अंतराल नहीं है।
ace_HongKongIndependence

19

टर्नरी ऑपरेटर ?:असामान्य है कि इसमें दो अलग-अलग टुकड़े हैं। इस वजह से, यह मानक ऑपरेटर पूर्वता नियमों के लिए एक खामियों का एक सा प्रदान करता है। यह कोष्ठक से बचने के लिए उपयोगी हो सकता है।

निम्नलिखित उदाहरण लें:

if (t()) a = b, b = 0;  /* 15 chars */

सामान्य गोल्फिंग दृष्टिकोण के ifसाथ बदलना है &&, लेकिन अल्पविराम ऑपरेटर की पूर्वता के कारण, आपको कोष्ठक की एक अतिरिक्त जोड़ी की आवश्यकता है:

t() && (a = b, b = 0);  /* still 15 chars */

टर्निरी ऑपरेटर के मध्य खंड को कोष्ठक की आवश्यकता नहीं है, हालांकि:

t() ? a = b, b = 0 : 0;  /* 14 chars */

इसी तरह की टिप्पणियाँ सरणी सदस्यता के लिए लागू होती हैं।


7
इस उदाहरण में, b-=a=bऔर भी छोटा है। ?:चाल, अभी भी उपयोगी है -=क्योंकि यह भी कम वरीयता है।
बदसूरत

अच्छी बात; मेरा उदाहरण अनावश्यक रूप से जटिल था।
ब्रेडबॉक्स

एक और बिंदु यह है कि कभी-कभी आप स्थिति को फ्लिप करना चाहते हैं: के लिए x>0||(y=3), x>0?0:(y=3)बेकार है, लेकिन x<1?y=3:0काम करता है।
बदसूरत

दोनों क्लेन्ग और जीसीसी टर्नरी में एक खाली सच्चे मामले के लिए अनुमति देते हैं । यदि छोड़ दिया जाता है, तो इसका मूल्य स्थिति का मूल्य है। उदाहरण के लिए,x>5?:y=1
क्रिस उज्दाविनिस 4

19

आपके कोड का कोई भी हिस्सा जो कई बार दोहराता है, प्री-प्रोसेसर के साथ प्रतिस्थापन के लिए एक उम्मीदवार है।

#define R return

यदि आप कोड एक से अधिक फ़ंक्शन शामिल करते हैं तो एक बहुत ही सामान्य उपयोग का मामला है। अन्य दीर्घाकार कीवर्ड की तरह while, double, switch, औरcase भी उम्मीदवार हैं; और साथ ही कुछ भी जो आपके कोड में मुहावरेदार है।

मैं आमतौर पर इस उद्देश्य के लिए अपरकेस चरित्र आरक्षित करता हूं।


1
एक छोटा प्रतिस्थापन होगा -DR=return। ध्यान दें कि यदि आप कुछ वर्णों को शामिल करते हैं, तो परिभाषित के आसपास सिंगल या डबल कोट्स होना आवश्यक हो सकता है -DP='puts("hello")'

15

यदि आपका प्रोग्राम प्रत्येक चरण में एक पर पढ़ रहा है या लिख ​​रहा है, तो हमेशा getchar के बजाय पढ़ने और लिखने के फ़ंक्शन का उपयोग करने का प्रयास करें () getchar () और ।

उदाहरण ( स्टडआउट पर स्टड और जगह को उल्टा करें) )

main(_){write(read(0,&_,1)&&main());}

व्यायाम: इस तकनीक का उपयोग करके यहां अच्छा स्कोर प्राप्त करें


प्रत्येक चरण के आधार पर आपका क्या मतलब है ?
केसी

केसी: मुझे लगता है कि उनका मतलब है अगर कार्यक्रम कुछ पढ़ रहा है, तो इस पर काम करता है, और आउटपुट लिखता है। एक स्ट्रीमिंग तरीके से, ऐसा कहने के लिए। एक दृष्टिकोण के विपरीत जहां एक ही बार में सभी इनपुट को पढ़ना और संभालना होता है।
जॉय

जॉय सही है, मेरा मतलब वही था, माफ करना मैंने आज तक अपना इनबॉक्स चेक नहीं किया।
18

8
यह स्टैक हेरफेर बहुत खूबसूरत है।
एंड्रिया बियोनडो

14

लूप्स को उलट दें

यदि आप कर सकते हैं, तो बदलने का प्रयास करें

for(int i=0;i<n;i++){...}

साथ में

for(int i=n;i--;){...}

13

यदि आपको कभी भी एक ही नईलाइन वर्ण ( \n) आउटपुट करने की आवश्यकता है , तो उपयोग न करें putchar(10), उपयोग करें puts("")


12

शून्य सामान पर वापसी मान का उपयोग करें। यदि आप कुछ फ़ंक्शन कहते हैं, और वह फ़ंक्शन सामान्य परिस्थितियों में शून्य देता है, तो आप इसे उस स्थान पर रख सकते हैं जहां शून्य की उम्मीद है। इसी तरह यदि आप जानते हैं कि धमाके के साथ फ़ंक्शन गैर-शून्य वापस आ जाएगा। सब के बाद, आप किसी भी मामले में कोड गोल्फ में उचित त्रुटि हैंडलिंग नहीं करते हैं, है ना?

उदाहरण:

close(fd);foo=0;   →  foo=close(fd);    /* saves two bytes */
putchar(c);bar=0;  →  bar=!putchar(c);  /* saves one byte  */

12

वापसी के बजाय असाइन करें।

यह वास्तव में मानक सी नहीं है, लेकिन हर संकलक और सीपीयू के साथ काम करता है जो मुझे पता है:

int sqr(int a){return a*a;}

के रूप में एक ही प्रभाव है:

int sqr(int a){a*=a;}

क्योंकि पहला तर्क रिटर्न मूल्य के रूप में एक ही सीपीयू रजिस्टर में संग्रहीत है।

नोट: जैसा कि एक टिप्पणी में कहा गया है, यह अपरिभाषित व्यवहार है और हर ऑपरेशन के लिए काम करने की गारंटी नहीं है। और किसी भी कंपाइलर ऑप्टिमाइज़ेशन को इस पर छोड़ दिया जाएगा।

एक्स-मैक्रो

एक अन्य उपयोगी विशेषता: एक्स-मैक्रोज़ आपकी मदद कर सकता है जब आपके पास चर की सूची होती है और आपको कुछ ऑपरेशन करने की आवश्यकता होती है जिसमें सभी शामिल होते हैं:

https://en.wikipedia.org/wiki/X_Macro


3
मैंने इसे उद्धृत किया और मुझे सही किया गया, यह बस सच नहीं है। यह केवल गुणा और भाग के साथ काम करेगा और जब अनुकूलन बंद हो जाएंगे। इसका कारण यह है कि दोनों ऑपरेशन ईआरएक्स में अपने परिणाम डालने के लिए होते हैं जो वापसी के लिए सामान्य रजिस्टर है। पैरामीटर या तो स्टैक या ईएक्सएक्स या एडएक्स में संग्रहीत होते हैं। इसे स्वयं आज़माएं।
गस्पा 79

3
आप सही हैं, यह अपरिभाषित व्यवहार है, यह कंपाइलर और आर्किटेक्चर पर भी निर्भर करता है, मैं आमतौर पर इस ट्रिक का उपयोग करके किसी भी उत्तर को पोस्ट करने से पहले x86 और armv7 पर gcc के साथ जांचता हूं। और निश्चित रूप से यदि आप अनुकूलन को सक्षम करते हैं, तो कोई भी स्मार्ट कंपाइलर अनावश्यक गुणन को हटा देगा।
जीबी

3
मैंने इस काम को जीसीसी के साथ नहीं बल्कि दूसरों के साथ देखा है
अल्बर्ट रेनशॉ

1
@ Gaspa79: gcc -O0हमेशा रिटर्न-वैल्यू रजिस्टर में भावों के मूल्यांकन के लिए चुनता है। मैंने x86, ARM और MIPS को कम से कम ( gcc.godbolt.org पर ) देखा है, और gcc ऐसा करने के लिए अपने रास्ते से बाहर जाने लगता है -O0। लेकिन याद रखें कि यदि आप इसका लाभ उठाते हैं, तो जिस भाषा में आप प्रोग्रामिंग कर रहे हैं gcc -O0, वह C नहीं है , और आपको अपने उत्तर को उसी के अनुसार लेबल करना चाहिए, C के रूप में नहीं । यह -O0डिबग मोड के अलावा किसी भी अनुकूलन स्तर पर विफल रहता है, और clang IIRC के साथ काम नहीं करता है।
पीटर कॉर्डेस

11
  1. किसी सरणी के पहले तत्व तक पहुँचने *aके a[0]लिए इसके बजाय का उपयोग करें ।

  2. संबंधित ऑपरेटर ( !=, >आदि) देते हैं 0या 1। क्या यह शर्त सही है या गलत है, इस पर निर्भर करता है: यदि और अन्यथा a[1+2*(i<3)]उपयोग किया जाएगा, a[1]तो अलग-अलग ऑफसेट देने के लिए अंकगणितीय ऑपरेटरों के साथ इसका उपयोग करें ।i >= 3a[3]


11
a[i<3?3:1]दो वर्णों से छोटा है a[1+2*(i<3)]
रेटो कोराडी

10

आप IOCCC अभिलेखागार (अंतरराष्ट्रीय obfuscated C कोड प्रतियोगिता) में देख सकते हैं।

एक उल्लेखनीय चाल # अल्पाइन मैक्रोज़ की है जिनके विस्तार में असंतुलित ब्रेसिज़ / कोष्ठक हैं, जैसे

#define P printf(

16
बेमेल कोष्ठक अपने आप में कोई मूल्य नहीं है। बिंदु जितना संभव हो उतना दोहराए जाने वाले पैटर्न को परिभाषित करना है। आप के साथ, आगे जाना चाह सकते हैं #define P;printf(
बदसूरत

यह छोटा बाइट कैसे गिना जाता है? शायद एक उदाहरण प्रदान करें?
साइओस

2
@ जवाब इस उदाहरण के लिए देखें ।
जोनाथन फ्रीच

8

for(int i=0;i<n;i++){a(i);b(i);} कुछ तरीकों से कम किया जा सकता है:

for(int i=0;i<n;){a(i);b(i++);} -1 लूप में ++अंतिम iमें जाने के लिए

for(int i=0;i<n;b(i++))a(i); -3 सभी को स्थानांतरित करने के लिए और अधिक लेकिन मुख्य लूप के शीर्ष और बाहर एक बयान, ब्रेसिज़ को हटाते हुए


अल्पविराम ऑपरेटर का उपयोग करना कुछ मामलों में ब्रेसिज़ से बचने का एक और तरीका है।
पीटर कॉर्डेस

8

कार्यात्मक जाओ!

यदि आप एक ही हस्ताक्षर के साथ सरल कार्यों के लिए अपनी समस्या को कम कर सकते हैं और एकल अभिव्यक्तियों के रूप में परिभाषित कर सकते हैं, तो आप #define r returnकिसी फ़ंक्शन को परिभाषित करने के लिए लगभग सभी बॉयलरप्लेट की तुलना में बेहतर और कारक-आउट कर सकते हैं ।

#define D(f,...)f(x){return __VA_ARGS__;}
D(f,x+2)
D(g,4*x-4)
D(main,g(4))

कार्यक्रम का परिणाम ओएस के लिए लौटाया गया स्थिति या शेल या आईडीई को नियंत्रित करना है।

उपयोग __VA_ARGS__करने से आप इन फ़ंक्शन-अभिव्यक्तियों में अनुक्रम बिंदुओं को प्रस्तुत करने के लिए अल्पविराम ऑपरेटर का उपयोग कर सकते हैं । यदि इसकी आवश्यकता नहीं है, तो मैक्रो छोटा हो सकता है।

#define D(f,b)f(x){return b;}

7
  1. scanf("%*d ");डमी इनपुट पढ़ने के लिए उपयोग करें। (यदि आगे के कार्यक्रम में इनपुट निरर्थक है) तो यह उस स्थान से कम है, scanf("%d",&t);जहाँ आपको वैरिएबल टी घोषित करने की आवश्यकता है।

  2. इंट अरेंजमेंट में कैरेक्टर्स को स्टोर करना कैरेक्टर एरे की तुलना में काफी बेहतर है। उदाहरण।

    s[],t;main(c){for(scanf("%*d ");~(c=getchar());s[t++]=c)putchar(s[t]);}


2
वास्तव में, मैं %*dन केवल गोल्फ में उपयोग करता हूं क्योंकि यह उन स्थितियों में भी उपयोगी है जहां कोई भी, उदाहरण के लिए, एक नई scanf("%[^\n]%*c",str);
रेखा

6

इसके बजाय कैरक्टर रिटर्न प्रिंट करें:

printf("%c\n",c);

या

putchar(c);putchar('\n'); // or its ascii value, whatever!

बस, c को इंट के रूप में घोषित करें और:

puts(&c);

9
यह संभवतः इंगित करने योग्य है कि यह थोड़ा-सा एंडियन आर्किटेक्चर पर निर्भर करता है। अगर c एक बड़ा एंडियन int है, तो आपको बस गाड़ी का रिटर्न मिलेगा। (दूसरी तरफ, अगर सी एक चर है, तो आपको गाड़ी वापसी के बजाय यादृच्छिक कचरा मिल सकता है।)
ब्रेडबॉक्स

@breadbox हां, आप पूरी तरह से सही हैं; मैंने अभी-अभी संपादित किया है: अंतिम अंश को c को int के रूप में उपयोग करना चाहिए (जो कि इस तरह की घोषणा करना अक्सर आसान होता है)।
मूला

puts(&c)वास्तव में काम करता है ? जरूरी नहीं कि यह शून्य-समाप्त हो।
बजे फल

1
@EsolangingFruit 32-बिट ints के साथ छोटे-एंडियन पर, एक int 0 <c <256 बाइट अनुक्रम c 0 0 0 के रूप में संग्रहीत किया जाता है । जब सी के पते की व्याख्या करते हैं के रूप में char *चरित्र:, हम एक सिंगलटन स्ट्रिंग देखने सी , एक अशक्त बाइट का स्थान है।
डेनिस

6

का उपयोग asprintf()कर आप स्पष्ट आवंटन बचाता है और यह भी एक स्ट्रिंग उर्फ ​​की लंबाई को मापने char*! यह शायद कोड गोल्फ के लिए बहुत उपयोगी नहीं है, लेकिन एक चार सरणियों के साथ रोजमर्रा के काम को आसान बनाता है। में कुछ और अच्छे सलाह हैं21 वीं शताब्दी सी

उपयोग उदाहरण:

#define _GNU_SOURCE
#include <stdio.h>

int main(int argc, char** argv) {
  char* foo;
  asprintf(&foo, "%s", argv[1]);
  printf("%s",foo);
}

6

import अगर आपको करना है

जैसा कि पहले ही उत्तर में कहा गया है , कुछ संकलक (विशेष रूप से, जीसीसी और क्लैंग) आपको चूक से दूर होने देते हैं#include लाइब्रेरी लाइब्रेरी फ़ंक्शंस के लिए s से ।

यहां तक ​​कि अगर तुम सिर्फ हटा नहीं सकते #include , तो इससे बचने के अन्य तरीके भी हो सकते हैं , लेकिन यह हमेशा व्यावहारिक या विशेष रूप से गोल्फ नहीं है।

शेष मामलों में, आप बाइट को बचाने के #import<header file>बजाय उपयोग कर सकते हैं #include<header file>। यह एक जीएनयू विस्तार है और इसे पदावनत माना जाता है, लेकिन यह कम से कम जीसीसी 4.8, जीसीसी 5.1 और क्लर्क 3.7 में काम करता है।


6

प्रयत्न, कोशिश cpow()इसके बजायcos()

के बजाय

double y=cos(M_PI*2*x);

कुछ ऐसा प्रयास करें

double y=cpow(-1,x*2);

यह यूलर के सूत्र , थोड़ा जटिल विश्लेषण और एक दोहरे को जटिल प्रदान करने वाले अवलोकन को वास्तविक भाग (वैरिएड फ़ंक्शन कॉल और अन्य सूक्ष्मता के साथ सावधान) का उपयोग करता है।

\ cos 2 \ pi x + j \ sin 2 \ pi x = e ^ {j2 \ pi x} = e ^ {j \ pi 2x} = (- 1) ^ {2x}

इस प्रकार की चाल को कम करने के लिए इस्तेमाल किया जा सकता है

double y=cpow(-1,x/2);

में

double y=cpow(1i,x);

चूंकि (-1) ^ \ frac {x} {2} = j ^ {\ frac {2x} {2}} = j ^ x


5

यहाँ मैं अपने लाभ के लिए इस्तेमाल किया है कुछ सुझाव दिए गए हैं। मैंने बेशर्मी से उन्हें दूसरों से चुराया है, इसलिए किसी को भी इसका श्रेय मैं:

फ़ंक्शन कॉल के साथ असाइनमेंट मिलाएं

इसके अलावा:

r = /* Some random expression */
printf("%d", r);

यह करो:

printf("%d", r = /* Some random expression */);

एक साथ कई चर आरंभ करें (जब संभव हो)

इसके अलावा:

for(i=0,j=0;...;...){ /* ... */ }

यह करो:

for(i=j=0;...;...){ /* ... */ }

शून्य / नॉनज़रो मान को संक्षिप्त करें

यह एक साफ-सुथरी चाल है जिसे मैंने यहां किसी से लिया है (याद नहीं है, माफ करना)। जब आपके पास एक पूर्णांक मान होता है और आपको इसे 1 या 0 में संक्षिप्त करने की आवश्यकता होती है, तो आप इसे !!आसानी से करने के लिए उपयोग कर सकते हैं। यह कभी-कभी अन्य विकल्पों जैसे के लिए फायदेमंद होता है ?:

इस स्थिति को लें:

n=2*n+isupper(s[j])?1:0; /* 24 */

आप ऐसा कर सकते हैं:

n=n*2+!!isupper(s[j]); /* 22 */

एक और उदाहरण:

r=R+(memcmp(b+6,"---",3)?R:0); /* 30 */

के रूप में फिर से लिखा जा सकता है:

r=R+R*!!memcmp(b+6,"---",3)); /* 29 */

1
शायद R*-~!!mxxxx
l4m2

5

बुनियादी तार्किक समानताएं जानने के बाद एक युगल बाइट्स को बचाने में सक्षम हो सकते हैं। उदाहरण के लिए, if (!(a&&b)){}DeMorgan के कानून का उपयोग करने के बजाय प्रयास करें if (!a||!b){}। यही बात बिटवाइज़ फ़ंक्शंस पर भी लागू होती है: बजाय ~(a|b)करने के ~a&~b


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.