C में दो कार्यों में क्या अंतर है?
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
अगर मैं फ़ंक्शन को काफी लंबे अरसे में कहता हूं, तो क्या ये दोनों फ़ंक्शन अलग-अलग व्यवहार करेंगे, क्या वे स्टैक पर अधिक स्थान लेंगे?
C में दो कार्यों में क्या अंतर है?
void f1(double a[]) {
//...
}
void f2(double *a) {
//...
}
अगर मैं फ़ंक्शन को काफी लंबे अरसे में कहता हूं, तो क्या ये दोनों फ़ंक्शन अलग-अलग व्यवहार करेंगे, क्या वे स्टैक पर अधिक स्थान लेंगे?
जवाबों:
सबसे पहले, कुछ मानक :
(प्रोटोटाइप सहित) 6.7.5.3 समारोह declarators
...
के रूप में '' की सरणी एक पैरामीटर के 7 एक घोषणा प्रकार '' को '' करने के लिए योग्य सूचक समायोजित किया जाएगा टाइप ', जहां प्रकार क्वालिफायर (यदि हो तो) उन निर्दिष्ट कर रहे हैं भीतर[
और]
सरणी प्रकार व्युत्पत्ति की। कीवर्ड हैंstatic
भी भीतर प्रकट होता है[
और]
सरणी प्रकार व्युत्पत्ति की, तो कार्य करने के लिए प्रत्येक कॉल के लिए, इसी वास्तविक तर्क का मूल्य कई तत्वों के रूप में कम से कम के रूप में आकार द्वारा निर्दिष्ट के साथ एक सरणी के पहले तत्व के लिए पहुँच प्रदान करेगा अभिव्यक्ति।
तो, संक्षेप में, किसी भी फ़ंक्शन पैरामीटर के रूप में घोषित किया जाता है T a[]
या T a[N]
माना जाता है जैसे कि यह घोषित किया गया था T *a
।
तो, सरणी पैरामीटर को ऐसे क्यों माना जाता है जैसे कि उन्हें संकेत के रूप में घोषित किया गया था? यहाँ पर क्यों:
6.3.2.1 Lvalues, सरणियों, और समारोह designators
...
जब इसके बारे में संकार्य है सिवाय 3sizeof
ऑपरेटर या एकल&
ऑपरेटर, या एक स्ट्रिंग एक सरणी को प्रारंभ करने के लिए इस्तेमाल शाब्दिक, एक अभिव्यक्ति प्रकार '' की सरणी है कि प्रकार ' 'प्रकार के साथ एक अभिव्यक्ति में बदल जाता है' 'पॉइंटर टू टाइप ' 'जो कि सरणी ऑब्जेक्ट के प्रारंभिक तत्व को इंगित करता है और एक अंतराल नहीं है। यदि एरे ऑब्जेक्ट में रजिस्टर स्टोरेज क्लास है, तो व्यवहार अपरिभाषित है।
निम्नलिखित कोड दिया गया है:
int main(void)
{
int arr[10];
foo(arr);
...
}
कॉल करने के लिए foo
, सरणी अभिव्यक्ति या arr
तो का एक ऑपरेंड नहीं है sizeof
या &
, इसलिए इसका प्रकार 6.2.3.1/3 के अनुसार "10-एलीमेंट int
" से "पॉइंटर int
" में परिवर्तित किया गया है। इस प्रकार, foo
एक सरणी मान के बजाय एक सूचक मान प्राप्त होगा।
6.7.5.3/7 के कारण, आप के foo
रूप में लिख सकते हैं
void foo(int a[]) // or int a[10]
{
...
}
लेकिन इसकी व्याख्या की जाएगी
void foo(int *a)
{
...
}
इस प्रकार, दो रूप समान हैं।
6.7.5.3/7 में अंतिम वाक्य C99 के साथ पेश किया गया था, और मूल रूप से इसका मतलब है कि यदि आपके पास पैरामीटर घोषणा जैसी है
void foo(int a[static 10])
{
...
}
वास्तविक पैरामीटर कम से कम 10 तत्वों के a
साथ एक सरणी होना चाहिए ।
अंतर विशुद्ध रूप से वाक्य रचना है। C में, जब फ़ंक्शन संकेतन के लिए सरणी संकेतन का उपयोग किया जाता है, तो यह स्वचालित रूप से एक सूचक घोषणा में बदल जाता है।
नहीं, उनमें कोई अंतर नहीं है। परीक्षण करने के लिए मैंने देव C ++ (mingw) संकलक में यह C कोड लिखा:
#include <stdio.h>
void function(int* array) {
int a =5;
}
void main() {
int array[]={2,4};
function(array);
getch();
}
जब मैं IDA में बाइनरी फ़ाइल के दोनों कॉलिंग संस्करणों के .exe में मुख्य फ़ंक्शन को इकट्ठा करता हूं तो मुझे नीचे की तरह एक ही विधानसभा कोड मिलता है:
push ebp
mov ebp, esp
sub esp, 18h
and esp, 0FFFFFFF0h
mov eax, 0
add eax, 0Fh
add eax, 0Fh
shr eax, 4
shl eax, 4
mov [ebp+var_C], eax
mov eax, [ebp+var_C]
call sub_401730
call sub_4013D0
mov [ebp+var_8], 2
mov [ebp+var_4], 4
lea eax, [ebp+var_8]
mov [esp+18h+var_18], eax
call sub_401290
call _getch
leave
retn
इसलिए इस कॉल के दो संस्करणों में कोई अंतर नहीं है, कम से कम संकलक उन्हें समान रूप से धमकी देता है।