2010-11-11 14 views
22

मैं सिर्फ देखा था इस hereसी कोड: ये कैसे काम करते हैं?

#include <stdio.h> 

int main(int argc, char *argv[printf("Hello, world!\n")]) {} 

यह क्या करता है प्रिंट है "नमस्ते दुनिया!"

लेकिन वास्तव में यहां क्या चल रहा है?

सबसे अच्छा मुझे लगता है कि कर सकते हैं कि यह संकलित और निष्पादन ढेर के शीर्ष पर फेंक दिया जाता है, लेकिन वाक्य रचना भी मेरे लिए कानूनी नहीं लगती है ...

उत्तर

21

कोड सी 99 की चर-लंबाई सरणी सुविधा का उपयोग करता है, जो आपको उन सरणी घोषित करने देता है जिनके आकार को केवल रन-टाइम पर जाना जाता है। printf वास्तव में मुद्रित वर्णों की संख्या के बराबर एक पूर्णांक देता है, इसलिए कोड प्रिंट करता है "हैलो, दुनिया!" पहले और argv के आकार के रूप में वापसी मान का उपयोग करता है। main फ़ंक्शन स्वयं कुछ भी नहीं करता है। printf पर वास्तविक कॉल शायद संकलक द्वारा उत्पन्न स्टार्टअप कोड में जाता है, जो बदले में main पर कॉल करता है।

संपादित करें: मैं सिर्फ gcc द्वारा बनाया गया कोड के disassembly की जाँच की और ऐसा लगता है कि printf करने के लिए कॉल के अंदर main ही चला जाता है, किसी भी अन्य कोड से पहले।

+0

'printf' पर कॉल निश्चित रूप से किसी भी पूर्व-' मेन 'स्टार्टअप कोड में नहीं जाता है। –

+0

@ आर ..: यह सिर्फ एक अनुमान था, और सबसे अच्छा मैं कर सकता हूं। यह संभवतः कहां निष्पादित किया जा सकता है? – casablanca

+0

@ आर ..: कोई बात नहीं, आप इसके बारे में सही हैं और मैंने अपने स्वयं के प्रश्न का उत्तर दिया। :) – casablanca

-1

मैं, कोई सी विशेषज्ञ हूँ लेकिन ऐसा लगता है कि कमांड लाइन तर्क एक ही समय में main के रूप में घोषित किए जाते हैं।

+4

नहीं प्रसाद और कैसाब्लांका को यह मिला है। – dmckee

4

char *argv[printf("Hello, world!\n")])

printf() मुद्रित अक्षरों की संख्या देता है।

तो

int main(int argc, char *argv[printf("Hello, world!\n")]) {}

printf() जोप्रिंट करने के लिए

int main(int argc, char *argv[14]) {}

प्लस एक फोन के बराबर है

+1

यह केवल तभी सच है जब प्रिंटफ सभी पात्रों को प्रिंट करने में सफल हो। – Puppy

5

अगर मैं यह पता लगाने कैसे संकलक यह पार्स, मैं इस अपडेट कर देंगे, लेकिन कम से कम वहाँ उन्हें कैसे कंपाइल करने के लिए के रूप में कोई अटकलबाजी होने की जरूरत है:


objdump --disassemble /tmp/hello (edited): 

080483c4 <main>: 
80483c4:  55      push %ebp 
80483c5:  89 e5     mov %esp,%ebp 
80483c7:  83 e4 f0    and $0xfffffff0,%esp 
80483ca:  83 ec 10    sub $0x10,%esp 
80483cd:  b8 a0 84 04 08   mov $0x80484a0,%eax 
80483d2:  89 04 24    mov %eax,(%esp) 
80483d5:  e8 22 ff ff ff   call 80482fc <[email protected]> 
80483da:  c9      leave 
80483db:  c3      ret  
80483dc:  90      nop 
80483dd:  90      nop 
80483de:  90      nop 
80483df:  90      nop 

लिनक्स निष्पादनयोग्य के बाद से 0x8048000 पर सामान्य रूप से आधारित हैं , printf के लिए तर्क का पता एक द्विआधारी की शुरुआत से 0x00004a0 की भरपाई पर है:


xxd /tmp/hello | grep 00004a0 

00004a0: 4865 6c6c 6f2c 2077 6f72 6c64 210a 0000 Hello, world!... 

तो, तार का पता धकेल दिया जाता है, और printf कि एक आर्ग के साथ कहा जाता है। उस स्तर पर जादुई कुछ भी नहीं, इसलिए सभी मजेदार सामान जीसीसी द्वारा किया गया था।

संबंधित मुद्दे