• پایان فعالیت بخشهای انجمن: امکان ایجاد موضوع یا نوشته جدید برای عموم کاربران غیرفعال شده است

نحوه ارسال مقادير به تابع در سي پلاس پلاس

A.S.Roma

کاربر تازه وارد
تاریخ عضویت
9 می 2006
نوشته‌ها
24
لایک‌ها
0
با سلام
همان طور كه ميدانيد براي ارسال يك مقدار به تابع در ++C مي توانيم از سه روش زير استفاده كنيم :
1-Call By Value
2-Call By Pointer
3-Call By Reference​
در صورت امكان در مورد نحوه ساز و كار اين روش توضيح بفرماييد.
پيشاپيش از لطف شما بزرگواران كمال تشكر را دارم.
 

Mehdi.T

کاربر فعال برنامه نویسی
کاربر فعال
تاریخ عضویت
30 سپتامبر 2005
نوشته‌ها
506
لایک‌ها
3
محل سکونت
In Search of Sunrise
اگر اجازه بدید ، من یک دست کاری در اول کار بکنم (البته تا جایی که می دونم)
1- by value
2- by reference
--
return by reference
--
و صدا زدن (نه ارسال آرگومان) تابع توسط اشاره گر که بحث پیچیده خودش رو داره(و نه هر تابعی)
----
فراخوانی تابع با مقدار
مثال :
کد:
void fun1(int arg1, int arg2);
void main() {
	int par1,par2 ;
	func1(par1,par2) ;
}

//end



// with return value
int func1(int arg) {
	statement ;
}
void main() { 
	int par,retValue;
	retValue = func1(par);
}

----
این مثال هم برای دو تای آخری
البته اشاره گر ها بحث حجیمی رو در توابع دارند
کد:
#include <stdio.h>
#include <conio.h>

int x ;
int &func(int *p)
{
	*p+=2;
   return *p;
}
void main() {
	func(&x) += 10  ;
   printf("\n%d",x);
   getch();
}
خروجی 12
*البته من سی ++ نمیدونم اگر اشتباهی کردیم ببخشید
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نظرم بهتره اين موضوع كنفرانس گذاشته بشود. خيلي ها مشكل دارند در اين مورد. من هم همچنين.
بگذاريد استارتر بياد نظرش را بگه تا ببينيم چطوري اين سرفصل را جمع و جور كنيم.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
من از روزي كه اين تاپيك باز شده دارم روي اين موضوع مطالعه مي كنم.
مثال زير به نظرم جالب بود.
برنامه زير، يك تابع داره كه ورودي اش با * تعيين شده. در تابع main با &x به اين خواسته تابع، پاسخ داده شده.
مي بينيم كه p در تابع احضار شده ، ماهيتش يك آدرس است.
نتيجه گيري: مي بينيم كه وقتي آدرس متغير يعني &x به تابع ارسال ميشه ، بعد برگشت از تابع ، x تغيير كرده.


b8.gif


من در اين برنامه آمدم در تعريف تابع f() علامت ستاره را برداشتم. و در خطهايي كه با رنگ آبي نشان داده شده error دريافت كردم.

کد:
#include <iostream.h>

void f([color=red]int p[/color]) {
  cout << "p = " << p << endl;
					 [color=blue]// cout << "*p = " << *p << endl;[/color]
					 [color=blue]//*p = 5; [/color]
  cout << "p = " << p << endl;
}

int main() {
  int x = 47;
  cout << "x = " << x << endl;
  cout << "&x = " << &x << endl;
  cout<<"----go to function----------"<<endl;
				  [color=blue]	// f(&x);[/color]
	 cout<<"----return from function-----"<<endl;
  cout << "x = " << x << endl;
} ///:~
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
حالا در تعريف تابع به جاي * ما ، & داريم. همان طور كه مي بينيد موقع صدا كردن تابع ، به شكل معمولي صدا شده ولي نتيجه ... .. معمولي نيست!!


b9.gif


من باز مثل پست قبل آمدم ، در تعريف تابع & را برداشتم ، ولي اين بار هيچ خطايي دريافت نكردم . ولي نتيجه مختلف بود كه خودتان مي دانيد چرا.


c1.gif


حالا من بدون استناد به كتابي ، و با نظر خودم ، مي خواهم يك نوع تقسيم بندي بكنم. هر جا غلط گفتم حتما اصلاح كنيد.


صدا كردن دو جوره :

کد:
f(x);
f(&x);

تابع صدا شده ، 3 جوره:

کد:
void f(int r)
void f(int &r)
void f(int *r)

وقتي تابع معمولي است ، صدا كردن معمولي است.
وقتي تابع * داره ، صدا كردن با & است.
وقتي تابع & داره. صدا كردن معمولي.
در نوع دوم و سوم ديديم كه مقدار متغير بعد از برگشت تغيير كرده بود.

مقدار برگشت داده شده ، كه اينجا نداريم چون void تعريف كرديم، هم مي تواند معمولي يا با آدرس باشه كه بعدا اگه شدبحث مي كنيم.
.
 

Arash_j13

Registered User
تاریخ عضویت
18 فوریه 2005
نوشته‌ها
778
لایک‌ها
2
محل سکونت
مشهد
تابع رو به دو صورت می شه فراخوانی کرد یا باد مقدار یا به وسیله ی ارجاع روش دیگه ای وجود نداره
در ارسال با مقدار کپی مقدار پامتر ها ارسال می شه ولی در ارسال با ارجاع یه ریفرنس به متغییر فرستاده می شه حتما با مفهموم ریفرنس ها آشنا هستید تغییر هایی که نام دومی برای متغییر دیگری هستند
در حالت معمولی پارمتر با مقدار ارسال می شن ولی اگه در هنگام تعریف تابع در پشت نام آرگومان یک & قرار بدیم یه ریفرنس دریافت می کنه ولی در زمان فراخوانی هیچ تغییری نیسبت به قبل لازم نیست انجام بدید و تابع رو به صورت معمول فراخوانی کنید ولی هر تغییری در آرگومان تابع باعث تغییر در مقدار متغییر می شه

یه نکته ای این وسط هست که اون هم اشاره گر ها هستن اشاره گر با مقدار پاس می شن ولی به خاطر نوع خاصشون که ادرس رو نگه داری می کنن می شه در مقدار متغییری که اشاره گر بهش اشاره می کنه دستکاری کرد و لی همچنان مقدار خودش اشاره گر که ادرس متغییر هست بی تغییر می مونه ما معمولا یه اشاره گر جداگانه برای ارسال ایجاد نمی کنیم بلکه با کمک عملگر آدرس & ادرس متغییر رو بدست می یاریم و ارسال می کنیم
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
ممنون آرش جان.
خيالم راحت شد.
----------------------
يك نكته اين كه وقتي تابع صدا زده شده تغييري بر متغيرهاي ارسالي بوجود نمي آورد، پس، آنچه تابع بازگشت ميده با return ميشه ماحصل كار تابع صدا شده و ما با آن كار مي كنيم.

ولي وقتي تابع صدا زده شده ، تغيير مي هد متغيرهاي ارسال شده را، خودش ميشه يك نوع مقدار بازگشت داده شده. و قبلا گفتيم چون تابع فقط يك return داره ، پس اگر چند خروجي از تابع مي خواهيد ، بايد توسط تغيير روي ورودي ها باشه.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
البته ربطي به سئوال اين تاپيك نداره ، ولي چون مربوط به تابع بود ، اين برنامه را اينجا گفتم.
از:


c2.gif



C++ allows functions to have default parameters. This is useful when a parameter should have a specified value when the caller does not supply a value. For example, suppose that the value 42 should be passed to the function f() when the caller does not supply a value. In that case, it would make the calling code somewhat simpler if this parameter value were supplied as a default value:

در سي++ تابع ها مي توانند پارامتر ديفالت داشته باشند. با انجام اين كار وقتي تابع بدون مقدار صدا بشه اين مقدار ديفالت مورد استفاده قرار مي گيرد.

کد:
#include <iostream.h>

void f(int x=42);
void f(int x)
{
 cout<<"x="<<x<<endl;
}

int main()
{
  f(29);
  f();
}



c3.gif

 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
pass-by-reference
pass-by-reference-to-const

کد:
#include "Car.h"

void f(Car& a)
{
  a.startEngine();                                 
  // ...
}

void g(const Car& b)                                
{
  b.startEngine();                                  
  // ...
}

main()
{
  Car x;
  f(x);
  g(x);
}

بكار بردن عبارت const چه تغييري در ماهيت كار ايجاد مي كند؟
من دنبال اينم. اگه ميشه كمي راهنمايي كنيد.
.
 

Mehdi.T

کاربر فعال برنامه نویسی
کاربر فعال
تاریخ عضویت
30 سپتامبر 2005
نوشته‌ها
506
لایک‌ها
3
محل سکونت
In Search of Sunrise
پست شماره 8 : بحث overload هست
و پست 9 : (البته من به مفاهیم شی گرایی واقف نیستم) بحث حفاظت از مقدار ارجاع داده شده است ، که شما در طی روال ایجاد شده(با پارامتری ز نوع const) توانایی تغییر مقدار ارجاع داده شده رو ندارید ، که در صورت تغییر با خطای زمان کامپایل روبرو می شوید
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
خوب شد بحث اورلود را گفتيد. در جاي مناسب اشاره خواهم كرد. شايد هم همين جا خوب باشد.
در مورد پست 9 هم،
راهنمايي خوبي كرديد.
من منظورم شي گرايي نبود. مثال مناسب نداشتم. اين مثال را گذاشتم.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
تفاوت سي و سي ++ در احضار تابع:

4.11: Does C even have "pass by reference"?

Answer: Not really. Strictly speaking, C always uses pass by value.
You can simulate pass by reference yourself, by defining
functions which accept pointers and then using the & operator
when calling, and the compiler will essentially simulate it for
you when you pass an array to a function (by passing a pointer
instead, see question 6.4 et al.), but C has nothing truly
equivalent to formal pass by reference or C++ reference
parameters. (However, function-like preprocessor macros do
provide a form of "call by name".)


از :
c faq
http://teddy.fcc.ro/cgi-bin/base/page.pl?page=6&c
 

saeedsmk

مدیر بازنشسته
تاریخ عضویت
6 سپتامبر 2003
نوشته‌ها
1,518
لایک‌ها
4
ممنون سالک جان
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نقل از saalek :
صدا كردن دو جوره :

کد:
f(x);
f(&x);

تابع صدا شده ، 3 جوره:

کد:
void f(int r)
void f(int &r)
void f(int *r)

وقتي تابع معمولي است ، صدا كردن معمولي است.
وقتي تابع * داره ، صدا كردن با & است.
وقتي تابع & داره. صدا كردن معمولي.
در نوع دوم و سوم ديديم كه مقدار متغير بعد از برگشت تغيير كرده بود.

[/b].

من 3 نوع صدا كردن تابع را در زير مي آورم:

کد:
f(a);
....
}
void f(int r)
{
….
}

اين روش معمولي بود ، كه يك كپي از a به تابع فرستاده ميشود.

در اينجا عدد فرستاده شده تغيير نمي كند.

کد:
f(a);
....
}
void f(int &r)
{
….
}

اين صدا كردن با آدرس است كه (( هيچ كپي ئي)) ساخته نمي شود و بخاطر ساخته نشدن كپي ، صرفه جويي در سرعت و حافظه مي شود.

در اينجا عدد فرستاده شده تغيير مي كند.

کد:
f(a);
....
}
void f(const int &r)
{
….
}

در اينجا هم كپي ساخته نمي شود ، پس باز صرفه جويي داريم . ولي عدد بخاطر وجود كلمه const تغيير نمي كند.

در اينجا عدد فرستاده شده تغيير نمي كند.
به نقل از MehdiTeh :
بحث حفاظت از مقدار ارجاع داده شده است ، که شما در طی روال ایجاد شده(با پارامتری از نوع const) توانایی تغییر مقدار ارجاع داده شده رو ندارید ، که در صورت تغییر با خطای زمان کامپایل روبرو می شوید
= = == = = = = = = = = = = = == =
در بالا ، 3 نوع احضار تابع را ديديم كه سومي زياد استفاده مي شود . احتمالا به خاطر صرفه جويي و امنيت .

در هر سه نوع ، ما موقع صدا كردن تابع از a استفاده كرده ايم نه &a .

خواهشا اگر چيزي اشتباه گفته شده ، تصحيح كنيد.
.
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نقل از MehdiTeh :
بحث حفاظت از مقدار ارجاع داده شده است ، که شما در طی روال ایجاد شده(با پارامتری از نوع const) توانایی تغییر مقدار ارجاع داده شده رو ندارید ، که در صورت تغییر با خطای زمان کامپایل روبرو می شوید


a2.gif

 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
در پستهاي بالا گفتيم كه هر گاه تابع با * منتظر مقدار باشد با & برايش مقدار مي فرستيم.
ولي هر گاه متغير از نوع اشاره گر باشد يا از نوع آرايه باشد ، چون خودش از نوع آدرس است ، پس ،، بدون & مي فرستيم.


a4.gif


کد:
#include <iostream.h>

void f(char *x,char *y,int *z);

void main()
{
char *a="bahaar";
char b[20]="tabestaan";
int c[3]={123,45,11};
  cout <<"  a= "<<a<<endl;
  cout <<"  b= "<<b<<endl;
  cout <<"  c= "<<c<<endl;
  f(a,b,c);
  }
 void f(char *x,char *y,int *z )
  {  cout<<endl<<endl;
 cout <<"  x= "<< x<<endl;
 cout<<"  y= "<<y<<endl;
 cout<<"  z= "<<z<<endl;
	}
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
ولي اعضاي يك آرايه مقدار هستند نه آدرس پس به شكل معمولي ارسال مي شوند.


a5.gif

 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
در مورد نوع char هم همين طور.


a6.gif


کد:
#include <iostream.h>

void f(char *x,char a,char b,char c  );

void main()
{
 char c[10]="abc";
	 cout <<"  c= "<<c<<endl;
	cout <<"  c[0]= "<<c[0]<<endl;
	cout <<"  c[1]= "<<c[1]<<endl;
	cout <<"  c[2]= "<<c[2]<<endl;
  f(c,c[0],c[1],c[2]);
  }
 // -------------------------------
void f(char *x,char a,char b,char c)
  {  cout<<endl<<endl;
 cout <<"  x= "<< x<<endl;
	cout<<"  a= "<<a<<endl;
	cout<<"  b= "<<b<<endl;
	cout<<"  c= "<<c<<endl;
	}
 

mikhak

کاربر تازه وارد
تاریخ عضویت
26 آپریل 2005
نوشته‌ها
10
لایک‌ها
0
سلام خسته نباشيد
خواستم يه پست بزنم تا بتونم شايد يه كمكي يا يه حرفي هم من زده باشم
سالك جان شرمنده از اينكه دخالت در امور ميكنم
بهتره به جاي اينكه بگيم
هر گاه تابع با * منتظر مقدار باشد با & برايش مقدار مي فرستيم.
بگيم چون مقدارش داره به يه جايي به يه آدرسي اشاره ميكنه موقع فرستادن هم آدرس متغير رو ميفرستيم چون در اين حالت بعضي ها فكر ميكنند كه متغير همراه يه & فرستاده ميشه كه يه نموره اين تيكش مورد داره
خيلي مخلصيم سالك جان
---------------------------
سينا
 

saalek

مدیر بازنشسته
تاریخ عضویت
24 می 2005
نوشته‌ها
654
لایک‌ها
53
محل سکونت
در پاي كوهپايه ها
به نقل از mikhak :
بگيم چون مقدارش داره به يه جايي به يه آدرسي اشاره ميكنه موقع فرستادن هم آدرس متغير رو ميفرستيم چون در اين حالت بعضي ها فكر ميكنند كه متغير همراه يه & فرستاده ميشه كه يه نموره اين تيكش مورد داره

سينا جان همين كه اينجا تشريف آورديد و پست زديد، چوب كاري كرديد.
هر چي شما بگيد درسته.
شما نياز به معرفي نداريد و گرنه معرفي مي كردم.
ممنونم از همه محبتهاي شما.
.
=======================
براي ارسال يك آرايه به تابع ، من از راه زير استفاده كردم. اگر اشكال داره بگيد. و راه صحيح اين كار را بگوييد.

کد:
#include <iostream.h>

f(int *x);

  void main()
{
int a[5]={12,24,55,21,44};
f(a);
}

f(int * x)
{
cout<<"x[0],x[1],x[2]= "<<x[0]<<","<<x[1]<<","<<x[2]<<endl;
}


a7.gif

 
بالا