printf()
डीबगिंग स्टेटमेंट्स की एक जोड़ी बताती है कि एक डबल पॉइंटर जो मैं गुजर रहा हूं वह है, जब प्राप्त करने वाले अंत में संदर्भित किया जाता है, तो एक अलग मूल्य के रूप में बाहर आ रहा है - लेकिन केवल माइक्रोसॉफ्ट विजुअल स्टूडियो (संस्करण 9.0) के तहत। चरणों काफी सरल हैं:एक printf() इस डबल को पॉइंटर द्वारा पारित करने की अनुमति क्यों देता है?
double rho=0; /* distance from the Earth */
/* ... */
for (pass = 0; pass < 2; pass++) {
/* ... */
rho = sqrt(rsn*rsn+rp*rp-2*rsn*rp*cpsi*cos(ll));
printf("\nrho from sqrt(): %f\n", rho);
/* ... */
}
/* ... */
cir_sky (np, lpd, psi, rp, &rho, lam, bet, lsn, rsn, op);
/* ... */
}
/* ... */
static void
cir_sky (
/* ... */
double *rho, /* dist from earth: in as geo, back as geo or topo */
/* ... */)
{
/* ... */
printf("\nDEBUG1: *rho=%f\n", *rho);
पूरे सी फ़ाइल यहाँ है:
मैं उम्मीद है कि पहले printf()
में प्रदर्शित मान ही होगा कि के रूप में प्रदर्शित किया जाएगा द्वारा दूसरा, एक डबल को पॉइंटर पास करने के बाद से एक अलग मूल्य नहीं होना चाहिए। और जीसीसी के तहत वे वास्तव में हमेशा एक ही मूल्य हैं। विजुअल स्टूडियो 32-बिट संकलन के तहत वे हमेशा एक ही होते हैं। लेकिन जब यह कोड 64-बिट आर्किटेक्चर के तहत विजुअल स्टूडियो के साथ संकलित किया गया है, तो दो डबल मान अलग हैं!
https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.18/job/4xu7abnl9vx3n770#L573
rho from sqrt(): 0.029624
DEBUG1: *rho=0.000171
यह चिंताजनक है। मैंने सोचा: क्या rho
के बीच कोड गणना की गई है और जहां पॉइंटर आखिरकार किसी भी तरह से खराब पॉइंटर अंकगणित द्वारा मूल्य को नष्ट कर देता है? तो मैं सही cir_sky()
कॉल ऊपर एक आखिरी printf()
कहा, देखने के लिए कि मूल्य पहले से ही उस समय तक या क्या यह कॉल खुद के पाठ्यक्रम में बदल दिया जाता है बदल दिया गया है:
printf("\nrho about to be sent: %f\n", rho);
cir_sky (np, lpd, psi, rp, &rho, lam, bet, lsn, rsn, op);
यहाँ में है कि रेखा है पूरी फ़ाइल के संदर्भ:
और लगता है क्या?
printf()
जोड़ना बग तय किया गया - rho
पर पॉइंटर को सही मान पर संदर्भित किया जा सकता है!
के रूप में यहां देखा जा सकता:
https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.19/job/s3nh90sk88cpn2ee#L567
rho from sqrt(): 0.029624
rho about to be sent: 0.029624
DEBUG1: *rho=0.029624
मैं चक्कर में पड़ कर रहा हूँ।
सी मानक का क्या बढ़िया मामला मैं यहां चल रहा हूं? इस फ़ंक्शन के शीर्ष-स्तरीय दायरे में केवल rho
मान का उपयोग क्यों करता है, माइक्रोसॉफ्ट कंपाइलर को इसके मूल्य को सही ढंग से संरक्षित करने के लिए मजबूर करता है? क्या समस्या rho
दोनों ब्लॉक के अंदर सेट और उपयोग की जाती है, और विजुअल स्टूडियो उस ब्लॉक के बाहर अपने मूल्य को संरक्षित करने के लिए अस्वीकार नहीं करता है क्योंकि सी मानक के क्विर्क की वजह से मैंने कभी आंतरिक रूप से आंतरिक नहीं किया है?
आप उपरोक्त AppVeyor लिंक पर संपूर्ण निर्माण आउटपुट देख सकते हैं। इस सी फ़ाइल के लिए विशेष रूप से संकलन कदम है, के मामले में समस्या हो सकती है कैसे दृश्य स्टूडियो लाया या संकलन विकल्प है, है:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\Bin\amd64\cl.exe /c /nologo /Ox /MD /W3 /GS- /DNDEBUG -Ilibastro-3.7.7 -IC:\Python27-x64\include -IC:\Python27-x64\PC /Tclibastro-3.7.7\circum.c /Fobuild\temp.win-amd64-2.7\Release\libastro-3.7.7\circum.obj
circum.c
libastro-3.7.7\circum.c(126) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(127) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(139) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(140) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(295) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(296) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(729) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
libastro-3.7.7\circum.c(730) : warning C4244: '=' : conversion from 'double' to 'float', possible loss of data
उन चेतावनियों में से कोई भी, मैं क्या देख सकते हैं से, कर रहे हैं में शामिल कोड के लिए यह विशेष पहेली - और यदि वे थे, तो वे सभी संकेत देंगे कि एक फ्लोट वैल्यू कम सटीक हो सकता है (दशमलव परिशुद्धता के लगभग 15 अंकों से 7), यह नहीं कि यह पूरी तरह से बदल सकता है।
यहां, दो संकलन-और-परीक्षण रनों के आउटपुट हैं, जिनमें से पहला असफल रहा और दूसरा - printf()
की वजह से? - सफल रहा:
https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.18/job/4xu7abnl9vx3n770
https://ci.appveyor.com/project/brandon-rhodes/pyephem/build/1.0.19/job/s3nh90sk88cpn2ee
दोनों AppVeyor के अनुसार, ठीक उसी वास्तुकला के लिए कर रहे हैं:
Environment: PYTHON=C:\Python27-x64, PYTHON_VERSION=2.7.x, PYTHON_ARCH=64, WINDOWS_SDK_VERSION=v7.0
आपने इसे 'पायथन' के साथ क्यों टैग किया? – BrenBarn
क्योंकि सी एक्सटेंशन को संकलित करते समय यह हो रहा है, लेकिन चूंकि त्रुटि एक 'printf' के बीच होती है और सी कोड में अन्य जो पाइथन को कॉल नहीं करती है, मैंने टैग हटा दिया है - और मुझे आशा है कि पाइथन लाइब्रेरी की उपस्थिति वास्तव में सचमुच सचमुच समस्या से कोई लेना देना नहीं है! –
क्या आप इलिप्सिस को '/ * ... * /' या कुछ समान के साथ बदल सकते हैं, या बस उन्हें पूरी तरह से हटा सकते हैं? यह कोड को पढ़ने के लिए वास्तव में कठिन बना रहा है। – Qix