۱-۳-۱۳۸۶, ۰۵:۱۸ عصر
اشاره گرها
یکی از مباحثی که برنامه نویسان مبتدی معمولا در آن با مشکل مواجه می شوند مبحث اشاره گر(pointer) میباشد.
در اینجا سعی می کنیم با زبانی ساده به معرفی و نحوه استفاده از اشاره گرها بپردازیم:
تعریف:اشاره گر،متغییری است که آدرسی از حافظه را نگه میدارد.همانطور که میدانید یک متغییر در خود به طور مستقیم یک مقدار را نگه میدارد اما یک اشاره گر به طور غیرمستقیم به یک مقدار اشاره میکند(از طریق آدرس).برای تعریف یک اشاره گر میبایست نوع داده ای که اشاره گر به آن اشاره می کند مشخص شود(مثلا int,double,float,…)البته لزومی ندارد که این انواع داده از انواع داده داخلی زبان باشد بلکه میتواند از انواع تعریف شده توسط برنامه نویس نیز باشد
برای تعریف اشاره گر پس از آوردن نوع داده از عملگر * استفاده میکنیم و سپس نامی برای اشاره گر انتخاب میکنیم.
مثال:
Int * x; اشاره گر از نوع صحیح
توجه کنید که داخل اشاره گر آدرس قرار میگیرد و ما مستقیما در آن آ درس را قرار میدهیم،برای این کار باید از عملگر & استفاده کنیم. با قرار دادن یک متغییر پس از & در واقع ما آدرس متغییر را به دست می آوریم که میتوان آن را مستقیما در متغییر اشاره گر قرار داد.
int x;
int * y=&x;
حال در اشاره گر y آدرس x قرار دارد.
توجه کنید که اگر پس از تعریف اشاره گر می خواستیم آدرسی را در آن قرار دهیم نباید از * استفاده کنیم چرا که پس از تعریف، این عملگر، عمل دیگری (dereferencing یا ارجاء) را انجام میدهد.یعنی با فرض اینکه y یک اشاره گر صحیح باشد و بخواهیم آدرس x را در آن قرار دهیم داریم :
y=&x;
و اما ارجاء :زمانی که بخواهیم از مقداری که اشاره گر به آن اشاره میکند استفاده کنیم باید توسط عملگر *، مقدار را برگردانیم در واقع توسط این عملگر به آدرس موجود در اشاره گر رفته ومقدار موجود در آن آدرس را باز می یابیم .
شکل زیر،شماتیکی برای pointerها نشان میدهد.دایره ای که در داخل فضای حافظه اشاره گر قرار دارد در واقع آدرس خانه حافظه intکه در داخل آن مقدارصحیحی(بیضی داخل شکل) قرار دارد، میباشد که استفاده از عملگر * قبل از اشاره گر، آن مقدار را برمیگرداند.
![[تصوير: 4klaz5h.gif]](http://i5.tinypic.com/4klaz5h.gif)
برای جلوگیری از پیچیدگی توصیه میشود کدهای زیر را اجرا کنید تا به مفهوم اشاره گر تسلط پیدا کنید:
دو برنامه زیر در واقع استفاده از pointerدر توابع را نشان میدهد(برنامه اول بدون استفاده از اشاره گر و دومی با استفاده از اشاره گر است) که البته تنها جنبه آ موزشی دارد:
توجه کنید که در اشاره گرها میتوان از اعمال ریاضی هم استفاده کرد .
فرض کنید در یک اشاره گرint با نام xآدرس حافظه 3002 ذخیره شده حال اگر این اشاره گر را با عددی مثل یک جمع کنیم آنگاه آدرس موجود در اشاره گر با sizeof(int)جمع می شود مثلا با فرض اینکه int به اندازه 4 بایت فضا بگیرد آنگاه مقدار آدرس برابر با 3006(3002+1*4) میشود در واقع ریاضیات اشاره گرها کار با واحدهای حافظه است.برنامه زیر را امتحان کنید:
حالا میتوان نشان داد که عملا آرایه ها با اشاره گرها ارتباط تنگاتنگی دارند و در واقع کار با آرایه کار با اشاره گر هاست.
زمانی که یک آرایه را به تابع ارسال میکنید در واقع آدرس خانه اول آن آ رایه را به تابع پاس می دهید و عملگر []در آرایه ها عمل ارجاء را انجام میدهد
در صورت وجود هر گونه اشکال لطفا توسط پست اطلاع دهید.
در صورت رضایت شما و آقا ی نخلبند مباحث پیشرفته تر در مورد pointerها را در هفته های بعد قرار میدهم.باتشکر.
توجه:کدهای استفاده شده از کتاب زیر استخراج شده اند:
c++ how to program
یکی از مباحثی که برنامه نویسان مبتدی معمولا در آن با مشکل مواجه می شوند مبحث اشاره گر(pointer) میباشد.
در اینجا سعی می کنیم با زبانی ساده به معرفی و نحوه استفاده از اشاره گرها بپردازیم:
تعریف:اشاره گر،متغییری است که آدرسی از حافظه را نگه میدارد.همانطور که میدانید یک متغییر در خود به طور مستقیم یک مقدار را نگه میدارد اما یک اشاره گر به طور غیرمستقیم به یک مقدار اشاره میکند(از طریق آدرس).برای تعریف یک اشاره گر میبایست نوع داده ای که اشاره گر به آن اشاره می کند مشخص شود(مثلا int,double,float,…)البته لزومی ندارد که این انواع داده از انواع داده داخلی زبان باشد بلکه میتواند از انواع تعریف شده توسط برنامه نویس نیز باشد
برای تعریف اشاره گر پس از آوردن نوع داده از عملگر * استفاده میکنیم و سپس نامی برای اشاره گر انتخاب میکنیم.
مثال:
Int * x; اشاره گر از نوع صحیح
توجه کنید که داخل اشاره گر آدرس قرار میگیرد و ما مستقیما در آن آ درس را قرار میدهیم،برای این کار باید از عملگر & استفاده کنیم. با قرار دادن یک متغییر پس از & در واقع ما آدرس متغییر را به دست می آوریم که میتوان آن را مستقیما در متغییر اشاره گر قرار داد.
int x;
int * y=&x;
حال در اشاره گر y آدرس x قرار دارد.
توجه کنید که اگر پس از تعریف اشاره گر می خواستیم آدرسی را در آن قرار دهیم نباید از * استفاده کنیم چرا که پس از تعریف، این عملگر، عمل دیگری (dereferencing یا ارجاء) را انجام میدهد.یعنی با فرض اینکه y یک اشاره گر صحیح باشد و بخواهیم آدرس x را در آن قرار دهیم داریم :
y=&x;
و اما ارجاء :زمانی که بخواهیم از مقداری که اشاره گر به آن اشاره میکند استفاده کنیم باید توسط عملگر *، مقدار را برگردانیم در واقع توسط این عملگر به آدرس موجود در اشاره گر رفته ومقدار موجود در آن آدرس را باز می یابیم .
شکل زیر،شماتیکی برای pointerها نشان میدهد.دایره ای که در داخل فضای حافظه اشاره گر قرار دارد در واقع آدرس خانه حافظه intکه در داخل آن مقدارصحیحی(بیضی داخل شکل) قرار دارد، میباشد که استفاده از عملگر * قبل از اشاره گر، آن مقدار را برمیگرداند.
![[تصوير: 4klaz5h.gif]](http://i5.tinypic.com/4klaz5h.gif)
برای جلوگیری از پیچیدگی توصیه میشود کدهای زیر را اجرا کنید تا به مفهوم اشاره گر تسلط پیدا کنید:
کد:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int a; // a is an integer
int *aPtr; // aPtr is a pointer to an integer
a = 7;
aPtr = &a; // aPtr assigned address of a
cout << "The address of a is " << &a
<< "\nThe value of aPtr is " << aPtr;
cout << "\n\nThe value of a is " << a
<< "\nThe value of *aPtr is " << *aPtr;
cout << "\n\nShowing that * and & are inverses of "
<< "each other.\n&*aPtr = " << &*aPtr
<< "\n*&aPtr = " << *&aPtr << endl;
return 0; // indicates successful termination
} // end mainکد:
#include <iostream>
using std::cout;
using std::endl;
int cubeByValue( int ); // prototype
int main()
{
int number = 5;
cout << "The original value of number is " << number;
// pass number by value to cubeByValue
number = cubeByValue( number );
cout << "\nThe new value of number is " << number << endl;
return 0; // indicates successful termination
} // end main
// calculate and return cube of integer argument
int cubeByValue( int n )
{
return n * n * n; // cube local variable n and return result
} // end function cubeByValueکد:
#include <iostream>
using std::cout;
using std::endl;
int cubeByValue( int ); // prototype
int main()
{
int number = 5;
cout << "The original value of number is " << number;
// pass number by value to cubeByValue
number = cubeByValue( number );
cout << "\nThe new value of number is " << number << endl;
return 0; // indicates successful termination
} // end main
// calculate and return cube of integer argument
int cubeByValue( int n )
{
return n * n * n; // cube local variable n and return result
} // end function cubeByValueفرض کنید در یک اشاره گرint با نام xآدرس حافظه 3002 ذخیره شده حال اگر این اشاره گر را با عددی مثل یک جمع کنیم آنگاه آدرس موجود در اشاره گر با sizeof(int)جمع می شود مثلا با فرض اینکه int به اندازه 4 بایت فضا بگیرد آنگاه مقدار آدرس برابر با 3006(3002+1*4) میشود در واقع ریاضیات اشاره گرها کار با واحدهای حافظه است.برنامه زیر را امتحان کنید:
حالا میتوان نشان داد که عملا آرایه ها با اشاره گرها ارتباط تنگاتنگی دارند و در واقع کار با آرایه کار با اشاره گر هاست.
زمانی که یک آرایه را به تابع ارسال میکنید در واقع آدرس خانه اول آن آ رایه را به تابع پاس می دهید و عملگر []در آرایه ها عمل ارجاء را انجام میدهد
کد:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int b[] = { 10, 20, 30, 40 };
int *bPtr = b; // set bPtr to point to array b
// output array b using array subscript notation
cout << "Array b printed with:\n\n"
<< "Array subscript notation\n";
for ( int i = 0; i < 4; i++ )
cout << "b[" << i << "] = " << b[ i ] << '\n';
// output array b using the array name and
// pointer/offset notation
cout << "\nPointer/offset notation where "
<< "the pointer is the array name\n";
for ( int offset1 = 0; offset1 < 4; offset1++ )
cout << "*(b + " << offset1 << ") = "
<< *( b + offset1 ) << '\n';
// output array b using bPtr and array subscript notation
cout << "\nPointer subscript notation\n";
for ( int j = 0; j < 4; j++ )
cout << "bPtr[" << j << "] = " << bPtr[ j ] << '\n';
cout << "\nPointer/offset notation\n";
// output array b using bPtr and pointer/offset notation
for ( int offset2 = 0; offset2 < 4; offset2++ )
cout << "*(bPtr + " << offset2 << ") = "
<< *( bPtr + offset2 ) << '\n';
return 0; // indicates successful termination
} // end main
بر نامه های زیر با استفاده از اشاره گر نوشته شده توصیه می شود آنها به طور دستی اجرا کنید و به تحلیل آنها بپردازید.
// Converting lowercase letters to uppercase letters
// using a non-constant pointer to non-constant data.
#include <iostream>
using std::cout;
using std::endl;
#include <cctype> // prototypes for islower and toupper
void convertToUppercase( char * );
int main()
{
char phrase[] = "characters and $32.98";
cout << "The phrase before conversion is: " << phrase;
convertToUppercase( phrase );
cout << "\nThe phrase after conversion is: "
<< phrase << endl;
return 0; // indicates successful termination
} // end main
// convert string to uppercase letters
void convertToUppercase( char *sPtr )
{
while ( *sPtr != '\0' ) { // current character is not '\0'
if ( islower( *sPtr ) ) // if character is lowercase,
*sPtr = toupper( *sPtr ); // convert to uppercase
++sPtr; // move sPtr to next character in string
} // end while
} // end function convertToUppercase
// This program puts values into an array, sorts the values into
// ascending order, and prints the resulting array.
#include <iostream>
using std::cout;
using std::endl;
#include <iomanip>
using std::setw;
void bubbleSort( int *, const int ); // prototype
void swap( int * const, int * const ); // prototype
int main()
{
const int arraySize = 10;
int a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
cout << "Data items in original order\n";
for ( int i = 0; i < arraySize; i++ )
cout << setw( 4 ) << a[ i ];
bubbleSort( a, arraySize ); // sort the array
cout << "\nData items in ascending order\n";
for ( int j = 0; j < arraySize; j++ )
cout << setw( 4 ) << a[ j ];
cout << endl;
return 0; // indicates successful termination
} // end main
// sort an array of integers using bubble sort algorithm
void bubbleSort( int *array, const int size )
{
// loop to control passes
for ( int pass = 0; pass < size - 1; pass++ )
// loop to control comparisons during each pass
for ( int k = 0; k < size - 1; k++ )
// swap adjacent elements if they are out of order
if ( array[ k ] > array[ k + 1 ] )
swap( &array[ k ], &array[ k + 1 ] );
} // end function bubbleSort
// swap values at memory locations to which
// element1Ptr and element2Ptr point
void swap( int * const element1Ptr, int * const element2Ptr )
{
int hold = *element1Ptr;
*element1Ptr = *element2Ptr;
*element2Ptr = hold;
} // end function swapدر صورت رضایت شما و آقا ی نخلبند مباحث پیشرفته تر در مورد pointerها را در هفته های بعد قرار میدهم.باتشکر.
توجه:کدهای استفاده شده از کتاب زیر استخراج شده اند:
c++ how to program