اشاره‌گرها در زبان ++C - الگوریتمستان
الگوریتمستان
5814.345.00
  »  

       

آشنایی با مفهوم و عملکرد اشاره‌گرها در زبان برنامه‌نویسی ++C و ارائه مثالهایی از کاربرد آن

http://www.aachp.ir آنچه می‌خوانید ویراست جدید نوشته‌ای است که اولین بار با عنوان «اشاره گر و کاربرد آن» شهریور ماه 1385 از طریق وبگاه برنامه‌نویسی و طراحی الگوریتم (عنوان و طرح پیشین وبگاه الگوریتمستان) منتشر شده بود.


آنچه در این نوشته می‌خوانید:

یکی از مهمترین مباحث کاربردی هر زبان برنامه‌نویسی، اشاره‌گر و مفهوم آن است که کاربرد گسترده‌ای در شاخه‌ی ساختمان داده‌ها نیز دارد. در این فرصت با مفهوم اشاره‌گر و همینطور روش تعریف آن در زبان ++C آشنا می‌شوید. باید توجه داشته باشید که سوای روش تعریف اشاره‌گر در این زبان، کلیت مفهوم آن در بین تمام زبان‌ها مشترک است.

    پیش از شروع بحث دو مطلب مهم را یادآوری می‌کنم:

    1- تک تک بایت‌های حافظه برای خود آدرسی دارند که یک عدد صحیح و مثبت است. این آدرس دقیقا مانند کد پستی عمل می‌کند. یعنی کاملا منحصربفرد بوده و می‌توان از آن برای ارجاع به بایت استفاده کرد.

    2- هر متغیری پس از تعریف، متناسب با نوع خود چند بایت از حافطه را اشغال می‌کند. این بایت‌ها همگی متوالی بوده و در حافظه پشت سر هم قرار دارند.

      

اشاره‌گر

  [بازگشت به فهرست]

به زبان ساده، اشاره‌گر نوعی متغیر است که محتوای آن آدرس یکی از خانه‌های حافظه‌ی کامپیوتر است. به این مثال توجه کنید:

      

long int a;
long int *b;
b = &a;

      

    دو خط اول متغیر a را به عنوان متغیر صحیح و b را یک اشاره‌گر صحیح معرفی می‌کنند. این تعریف اشاره‌گر به کامپایلر می‌گوید که آدرس موجود در اشاره‌گر b مربوط به یک متغیر صحیح است. توسط خط سوم آدرس متغیر a در b قرار می‌گیرد. مثلا اگر متغیر a بایت‌های شماره‌ی 1000 تا 1003 را در اختیار داشته باشد، مقدار 1000 برای متغیر b در نظر گرفته می‌شود. اصطلاحا گفته می‌شود که اشاره‌گر b به a اشاره می‌کند. اینجا ممکن است دو سوال پیش بیاید: چرا فقط آدرس بایت اول در اشاره‌گر قرار می‌گیرد؟ و چرا برای اشاره‌گر نوع تعیین می‌شود؟ مگر نه اینکه آنها حاوی آدرس حافظه هستند؟ به چه دلیل نوع محلی که اشاره‌گر به آن اشاره دارد مشخص می‌شود؟

    به مثال زیر توجه کنید:

      

long int a, *b, c;
a = 69355;
b = &a;
c = *b;

      

    عبارت b* را بخوانید: «محتوای محلی که متغیر b به آن اشاره دارد». پس خط آخر مقدار 69355 را به c اختصاص می‌دهد (به کاربردهای متفاوت اپراتورهای & و * دقت کنید). فرض کنیم بایت‌های شماره‌ی 1000 تا 1003 برای ذخیره کردن مقدار متغیر a استفاده شده باشند (فرض کرده‌ایم متغیر از نوع long int چهار بایت اندازه دارد). پس اشاره‌گر b مقدار 1000 را دارد. وقتی برنامه به خط آخر می‌رسد، باید محتوای محلی را که b به آن اشاره می‌کند، در متغیر c قرار دهد. اما از کجا متوجه می‌شود که علاوه بر بایت شماره‌ی 1000 باید سه بایت بعدی را هم استفاده کند؟ و چطور متوجه می‌شود که باید این چهار بایت را به صورت عدد صحیح تفسیر کند؟ ممکن است این چهار بایت مربوط به یک عدد اعشاری چهار بایتی float باشد. به همین خاطر است که نوع اشاره‌گر تعیین می‌شود. وقتی اشاره‌گر b از نوع long int مشخص شده است، برنامه متوجه می‌شود که باید از چهار بایت به صورت عدد صحیح استفاده کند. اگر تعیین نوع برای اشاره‌گر انجام نمی‌شد، مشکلات زیادی به وجود می‌آمد. البته زبان برنامه‌نویسی ++C اشاره‌گرهای بدون نوع (void) هم دارد که کاربرد اختصاصی خود را دارند.

      

اشاره‌گرها و توابع

  [بازگشت به فهرست]

مطمئنا کاربرد اشاره‌گرها تنها محدود به مثال بالا نمی‌شود. یکی از کاربردهای مهم اشاره‌گر مربوط به انتقال داده‌ها بین توابع مختلف در برنامه است. متغیرهایی که در حالت عادی به عنوان پارامتر به یک تابع ارسال می‌شوند، از تغییر پیدا کردن توسط تابع مصون هستند. چرا که تابع یک کپی از آنها را دریافت می‌کند. به عنوان مثال:

      

void func(int n){
    n++;
}
  
void main(){
    int n = 10;
    func(n);
    cout << n;
}

      

    متغیر n مربوط به تابع func یک واحد افزایش پیدا می‌کند. اما این تغییر تاثیری در متغیر n در تابع اصلی ندارد. پس عدد 10 توسط cout به خروجی ارسال می‌شود. اما مواقعی هست که ما نیاز داریم بتوانیم مقدار متغیر را تغییر دهیم. مانند تابعی که دو متغیر را دریافت کرده و مقدار آنها را با هم عوض می‌کند. اینجا اشاره‌گر به کمک می‌آید:

      

void swap(int *a, int *b){
    int t;
    t = *a;
    *a = *b;
    *b = t;
}
  
void main(){
    int m = 15, n = 10;
10     swap(&m, &n);
11     cout << "m = " << m << " , n = " << n;
12 }

      

    به جای محتویات متغیرهای m و n، آدرس حافظه‌ی آنها به تابع ارسال می‌شود. پس اشاره‌گر a به m و اشاره‌گر b به n اشاره می‌کنند. حال به مراحل مختلف تابع swap توجه کنید:

    خط دوم: محتوای محلی که a به آن اشاره دارد (یعنی مقدار m) در t قرار می‌گیرد. پس t = 15.

    خط سوم: محتوای محلی که b به آن اشاره دارد (یعنی مقدار n) در محلی که a به آن اشاره دارد (یعنی m) ریخته می‌شود. پس m = 10.

    خط چهارم: محتوای t به محلی که b به آن اشاره دارد (یعنی n) وارد می شود. پس n = 15.

    بعد از این که کنترل به تابع اصلی باز می‌گردد، مقادیر m و n با هم عوض شده‌اند و خروجی به این صورت است:

      

m = 10, n = 15

      

اشاره‌گرها و آرایه‌های پویا

  [بازگشت به فهرست]

مهم‌ترین و اصلی‌ترین کاربرد اشاره‌گرها مربوط به کار با متغیرهای پویا است. متغیرهای عادی که در برنامه‌ها مورد استفاده قرار می‌گیرند ایستا هستند. یعنی حافظه‌ی آنها توسط خود برنامه اختصاص داده شده و در پایان نیز توسط خود برنامه آزاد می‌شوند. متغیرهای پویا عکس این حالت هستند. یعنی باید خودتان حافظه بگیرید و خودتان آزاد کنید. این نوع متغیر توسط اشاره‌گر کنترل می‌شود. به مثال ساده‌ی زیر توجه کنید:

      

void main(){
    int *p;
    p = new int;
    *p = 5;
    cout << *p;
    delete p;
}

      

    توسط دستور new حافظه‌ای به عنوان عدد صحیح رزرو شده و آدرس آن در اشاره‌گر p قرار می‌گیرد. بعد از انجام دادن هر عملیات دلخواه روی مقدار ذخیره شده در این حافظه، با استفاده از دستور delete حافظه آزاد می‌شود.

    تخصیص حافظه نیز دو کاربرد بسیار مهم دارد: آرایه‌های پویا و پیاده‌سازی ساختارهای مبحث ساختمان داده‌ها.

      

اشاره‌گر به تابع

  [بازگشت به فهرست]

زمانی که یک برنامه اجرا می‌شود، کدهای مورد نیاز آن در حافظه‌ی اصلی کامپیوتر بارگذاری می‌شوند. بنابراین کدهای برنامه نیز همانند متغیرهای مورد استفاده در آن شامل آدرسی هستند. هر تابع بلوکی از حافظه را در اختیار می‌گیرد که آدرس شروع آن به عنوان آدرس تابع در نظر گرفته می‌شود. یک اشاره‌گر امکان نگهداری چنین آدرسی را نیز دارد.

    تعریف چنین اشاره‌گری را با یک مثال نشان می‌دهم. فرض کنید تابعی به صورت زیر داریم:

      

long int func(int m, float n);

  

    اشاره‌گر به چنین تابعی اینگونه تعریف می‌شود:

      

long int (*p)(int, float);

      

    این تعریف مشخص می‌کند که p یک اشاره‌گر به مجموعه توابعی است که دو پارامتر به ترتیب از نوع int و float دارند و یک متغیر صحیح از نوع long int بر می‌گردانند. آدرس هر تابعی که چنین ساختاری داشته باشد می‌تواند در اشاره‌گر p قرار بگیرد. به قرار دادن پرانتز در دو طرف تعریف اشاره‌گر p هم توجه داشته باشید. نبود این پرانتزها تعبیر دیگری را برای کامپایلر تداعی می‌کند که در نهایت به خطا منجر می‌شود.

    پس از تعریف چنین اشاره‌گری، با دستور انتساب‌های زیر می‌توانید آدرس تابعی را در آن قرار دهید:

      

p = func;
p = &func;

      

    هر دو دستور آدرس تابع func را در اشاره‌گر p قرار می‌دهند.

    پس از این مقداردهی می‌توانید از اشاره‌گر برای فراخوانی تابع استفاده کنید:

      

cout << p(6, 7.5);

      

    این خط معادل دستور زیر است:

      

cout << func(6, 7.5);

      

    اشاره‌گر به توابع کاربردهای ویژه‌ای دارد که بحث جداگانه‌ای را می‌طلبد.

      

اشاره‌گر به ساختمان و کلاس

  [بازگشت به فهرست]

متغیرهای تعریف شده از ساختمان‌ها و کلاس‌ها نیز همچون متغیرهای عادی فضایی در حافظه‌ی کامپیوتر در اختیار می‌گیرند که می‌توان اشاره‌گر به آنها تعریف کرد. فرض کنید ساختمانی با تعریف زیر داریم:

      

struct student{
    char name[100];
    float average;
    int age;
};

      

    با داشتن چنین ساختاری دستورات زیر معتبر هستند:

      

student st, *p;
p = &st;
(*p).age = 14;

      

    در خط اول متغیر st از نوع ساختمان student و اشاره‌گر p به این نوع ساختمان تعریف شده است. در خط بعدی آدرس متغیر st در اشاره‌گر p قرار گرفته و در خط آخر محتوی فیلد age مربوط به محلی که p به آن اشاره دارد (در اینجا st) برابر 14 می‌شود.

    در زبان برنامه‌نویسی ++C روش دیگری نیز برای دسترسی به فیلدهای یک ساختمان از طریق اشاره‌گر وجود دارد. دو عبارت زیر معادل هم هستند:

      

(*p).age = 14;
p->age = 14;

      

    استفاده از عملگر <- خوانایی برنامه را بیشتر می‌کند.

      

اشاره‌گر به اشاره‌گر

  [بازگشت به فهرست]

اشاره‌گر متغیری است که محتوای آن آدرس خانه‌ای از حافظه است. پس خود این اشاره‌گر هم در خانه‌ای از حافظه قرار دارد. اشاره‌گر به اشاره‌گر متغیری است که آدرس خانه‌ی حافظه‌ای را در خود نگه می‌دارد که محتوای آن خود آدرس یکی از خانه‌های حافظه است. به عبارت دیگر، محتوای اشاره‌گر معمولی آدرس خانه حافظه‌ی متغیرهایی از نوع متغیرهای استاندارد غیر اشاره‌گر زبان برنامه‌نویسی ++C و ساختمان‌ها و کلاس‌ها و توابع است. اما اشاره‌گر به اشاره‌گر آدرس خانه‌ی حافظه‌ی متغیری از نوع اشاره‌گر معمولی را نگه می‌دارد.

    برای تعریف چنین اشاره‌گری از ** استفاده می‌کنیم:

      

int a;
int *p1 = &a;
int **p2 = &p1;

      

    اشاره‌گر به اشاره‌گر کاربردهای مهمی مانند تعریف آرایه‌های پویای دو بعدی دارد.

      

عملیات ریاضی روی اشاره‌گرها

  [بازگشت به فهرست]

محتوای یک اشاره‌گر آدرس خانه‌ی حافظه است که یک عدد صحیح است. روی این عدد صحیح می‌توان دو عمل جمع و تفریق را انجام داد. اما این عملیات محدودیت‌ها و نکاتی را شامل می‌شود.

    آدرس خانه‌ی حافظه را می‌توان به شماره‌ی پلاک منازل تشبیه کرد. ما هیچ دو شماره‌ی پلاک را با هم جمع یا از هم کم نمی‌کنیم. در مورد اشاره‌گرها هم اینگونه است و نمی‌توان دو اشاره‌گر را جمع و یا یکی را از دیگری کم کرد. اما می‌توان عدد صحیحی را به آن اضافه نمود یا از آن کم کرد:

      

long int a = 100, *b, *c;
b = &a;
c = b + 1;
c++;

      

    فرض کنیم متغیر a از خانه‌ی شماره 1000 شروع شده باشد. پس مقدار b با توجه به دستورات فوق 1000 خواهد بود. در خط بعدی b را با عدد یک جمع زده و در c قرار می‌دهیم. اما مقدار اشاره‌گر c بر خلاف حالت عادی 1001 نخواهد شد. متغیر c یک اشاره‌گر به عدد صحیح بزرگ است. زمانی که آن را با عدد یک جمع می‌زنیم، این اشاره‌گر به اندازه‌ی فضای مصرفی عدد صحیح بزرگ (در اینجا چهار بایت) پیش رفته و به خانه‌ی 1004 اشاره خواهد کرد. به همین ترتیب اگر از b یک واحد کم می‌کردیم به جای 999 به خانه‌ی شماره 996 اشاره می‌کرد. دلیل این مسئله هم مشخص است. این چهار بایت در کنار هم معنی عدد صحیح بزرگ را دارند و حرکت در داخل بایت‌های آن معنی ندارد. اگر اشاره‌گر به نوع دیگری تعریف شده بود، دقیقا به میزان فضای مصرفی همان نوع حرکت به جلو یا عقب صورت می‌گرفت. در خط آخر قطعه کد بالا هم باز یک پیش‌روی به جلو صورت گرفته و مقدار 1008 در خود اشاره‌گر c قرار می‌گیرد.


این نوشته آخرین بار در تاریخ دوشنبه، ۱۶ شهریور ماه ۱۳۹۴ مورد بازنویسی نگارشی قرار گرفته است.
نوشته‌های مرتبط
        معرفی انواع ظرف‌ها (نگهدارنده‌ها - containers) در زبان برنامه‌نویسی ++C
        آشنایی با درخت جستجوی دودویی (Binary Search Tree) و عملیات جستجو و درج و حذف گره
        معرفی فایل سرآیند algorithm از کتابخانه قالب استاندارد زبان برنامه‌نویسی ++C به همراه نمونه کد
        آشنایی با صف اولویتی (Priority Queue)، کاربردها و نحوه‌ی پیاده‌سازی آن
        آشنایی با کلاس‌های حافظه و کاربرد آنها در زبان ++C
        آشنایی با درخت Heap (هیپ، هرم یا کپه) به عنوان یکی از ساختمان های داده پرکاربرد و بررسی روش ساخت، درج گره و حذف گره و ارائه‌ی کد نمونه به زبان برنامه‌نویسی ++C
        آشنایی با حلقه‌های تکرار در زبان برنامه‌نویسی ++C و دستورات کنترلی مورد استفاده در آن
        بررسی مفهوم و روش پیاده‌سازی لیست پیوندی و توابع مرتبط آن به زبان برنامه‌نویسی ++C
        پنج نکته‌ی آموزنده در مورد برنامه‌نویسی به زبان برنامه‌نویسی ++C
        آشنایی با توابع دوست کلاس در زبان برنامه‌نویسی ++C و کاربرد آنها در سربارگذاری عملگرها
پیوند کوتاه صفحه دسته‌بندی
امتیاز نوشته
  • 1
  • 2
  • 3
  • 4
  • 5
ارسال پیام

نام: *  

پست الکترونیک:

وبگاه:

متن پیام: *

 


» محمد

چهارشنبه، ۹ دی ماه ۱۳۸۸، ساعت ۱۶:۲۱
چطور میشه آرایه پویای چند بعدی تعریف کرد؟


چهارشنبه، ۹ دی ماه ۱۳۸۸، ساعت ۱۷:۵۹
مسعود:
از چه بعدی مد نظرته محمد جان؟

» فرهاد

دوشنبه، ۹ فروردین ماه ۱۳۸۹، ساعت ۱۶:۳۱
لطفا برنامه ی یک ماشین حساب ساده با جمع و ضرب و تقسیم و توان و سینوس و کسینوس و ac را توضیح دهید

» مهدی

سه‌شنبه، ۱۱ خرداد ماه ۱۳۸۹، ساعت ۲۲:۱۷
می خواستم چگونگی تعریف و فراخوانی آرایه دو بعدی پویا n*n رو توضیح بدید.

» فاطمه

یکشنبه، ۱۸ اردیبهشت ماه ۱۳۹۰، ساعت ۱۴:۲۰
سلام من می خوام بدونم در زبان c چطور می تونیم متغیری که به صورت محلی تعریف کردیم مقدارش را نگهداری کنیم که  خارج از زیربرنامه ای که درآن تعریف شده به مقدارش دسترسی پیدا کنیم.

» ماهان

جمعه، ۲۳ اردیبهشت ماه ۱۳۹۰، ساعت ۰۱:۱۵
سلام.
یه  
char* A[10];
تعریف میکنم ویک سری اسم درونش میریزم وقتی که میخوام
اسمها رو مرتب کنم باید از سوپ استفاده کنم
ام ارور میگیره
مثلا میگه این آرایه دارای مقداز است ودیگه مقدار نمیگیره

» cyrus

دوشنبه، ۲ خرداد ماه ۱۳۹۰، ساعت ۰۰:۱۷
ممنون از مطلبتون،من تو كار با اشاره گرهاي 2 بعدي به مشكل بر خوردم ميشه راهنماييم كنيد؟

»  ---

جمعه، ۴ آذر ماه ۱۳۹۰، ساعت ۱۳:۱۴
20

» قاسم شمسيني

چهارشنبه، ۱۴ دی ماه ۱۳۹۰، ساعت ۱۶:۰۶
سلام خسته نباشيد

يك سوالي داريم اگه بتونيد جوابشو بگيد ممنون ميشيم

با استفاده از مکانیسم اشاره گرها  تابعی بنویسید که یک رشته را بصورت پارامتر  دریافت نموده تمام فضاهای خالی آن را حذف نماید وبه تابع اصلی بر گشت دهد

با تشكر

» مرجان

دوشنبه، ۱۱ دی ماه ۱۳۹۱، ساعت ۲۲:۵۷
سلام
میشه در مورد محیط windows forms application توضیح بدید که اصلا برای چی هست و چطوری میشه اون رو توی مدت کوتاهی یاد گرفت؟

» atefeh

دوشنبه، ۸ مهر ماه ۱۳۹۲، ساعت ۲۱:۲۱


void main( )

{

    int *p;

    p = new int;

    *p = 5;

    cout << *p;

    delete p;

}

man mikham ein barnamaro to c++builder run konam,ama error mide,barayerafe error kodom ghesmate barnamaro bas tagheir bedam?

» علی

شنبه، ۲۱ شهریور ماه ۱۳۹۴، ساعت ۱۸:۱۵
سلام
طبق بیان شما این تعریف یک اشاره گره :
int *p
حالا اگر علامت * بیاد اول تعریف چه اتقاقی می افته؟ مثل زیر :
*(int p)=0x21DF4521

حقیقتش من یک خط کد دیدم نفهمیدم منظورش چیه که در زیر می بینیدش:
*((volatile unsigned long *)(0x202FA34D))=0x21D4FF6A;


شنبه، ۲۱ شهریور ماه ۱۳۹۴، ساعت ۱۸:۴۵
مسعود:
به طور خلاصه این عبارت مقدار 0x21D4FF6A رو با شروع از آدرس شماره‌ی 0x202FA34D به عنوان یه unsigned long در حافظه می‌نویسه.
عبارت (volatile unsigned long *)(0x202FA34D) یعنی محل حافظه با شروع از آدرس حافظه‌ی 0x202FA34D از نوع unsigned long در نظر گرفته شه. اگه این عبارت رو با p نشون بدیم، کل عبارت به p = 0x21D4FF6A* تبدیل می‌شه که مفهومش مشخصه.
در مورد کلمه‌ی کلیدی volatile توضیحاتی در نوشته با عنوان «نکات مهم در برنامه‌نویسی به زبان ++C» اومده.

» amiri

شنبه، ۵ دی ماه ۱۳۹۴، ساعت ۱۷:۴۶
با سلام و عرض خسته نباشید : لطفا منو راهنمایی کنید. عدد 5.120170838794 را در نظر بگیرید،  عدد صحیح 5  تا دو رقم اعشار موقع قراثت توسط میکرو ثابت هستند ؛ ولی اعداد بعد از دو رقم اعشار (0170838794) ثابت نیستند و مرتب بالا و پایین میشوند (ولتاژ AC که کاملا به DC تبدیل نشده ،بنابراین اعداد بعد از اعشار هیچ وقت ثابت نیستند و .......)  حالا چطوری میشه این اعداد شناور بعد از دو رقم اعشار را که مرتب بالا و پایین میشوند را حذف کنم که میکرو فقط عدد 5.12 را درنظر بگیره یا اینکه کل از کل عدد یک average بگیره و  یک عدد ثابت به عنوان خروجی  تحویل بده. با تشکر فراوان06

» صادق

شنبه، ۱ اسفند ماه ۱۳۹۴، ساعت ۰۰:۵۵
سلام

سه خط آخر چه مفهومی داره؟

هر چقدر بررسی کردم بجایی نرسیدم!

unsigned char *ptr1,*ptr2;
int x=240;
ptr1=(unsigned char *)&x;
ptr2=(unsigned char *)360;
ptr2=ptr2+1;


تشکر


شنبه، ۱ اسفند ماه ۱۳۹۴، ساعت ۱۵:۲۰
مسعود:
سلام

خط سوم آدرس متغیر x در حافظه‌ی اصلی (RAM) رو داخل اشاره‌گر ptr1 قرار می‌ده.
خط چهارم اشاره‌گر ptr2 رو به محل 360 حافظه (که اطلاع نداریم شامل چه مقداری هست) مربوط می‌کنه.
خط پنجم باعث می‌شه اشاره‌گر ptr2 به یک خانه جلوتر (یعنی 361) از حافظه اشاره کنه.

» صادق

شنبه، ۱ اسفند ماه ۱۳۹۴، ساعت ۱۶:۵۴
سلام

ممنونم از پاسخ شما

چیست؟  (unsigned char *) در اینصورت هدف از

تشکر


شنبه، ۱ اسفند ماه ۱۳۹۴، ساعت ۱۸:۰۱
مسعود:
خواهش می‌کنم.

در مورد ptr1 چون این اشاره‌گر از نوع char هست، باید به صورت موقت آدرس متغیر x (که عدد صحیح هست) به آدرس char (اشاره به یک بایت) تبدیل شه که در واقع باعث می‌شه ptr1 به کم‌ارزش‌ترین بایت عدد x (شامل عدد 240) اشاره کنه.
در مورد ptr2 عدد 360 یک عدد صحیح هست و باید تغییر موقت با استفاده از این دستور صورت بگیره تا کامپایلر اون رو به صورت آدرس حافظه در نظر بگیره.

» صادق

یکشنبه، ۲ اسفند ماه ۱۳۹۴، ساعت ۰۳:۲۷
مجددا سلام

حقیقتش خیلی گیج شدم!

رو درک کنم  (unsigned char *)نتونستم

چون چند مثال دیدم، که توی هر کدوم یجور خاصیت داشت

مثال 1

int *ptr=(int *)1000;
ptr=ptr+1;
printf("New Value of ptr : %u",ptr);

//Output :
//New Value of ptr : 1002

مثال 2

double *ptr=(double *)1000;
ptr=ptr+1;
printf("New Value of ptr : %u",ptr);

//Output :
//New Value of ptr : 1004

مثال 3

float *ptr1=(float *)1000;
float *ptr2=(float *)2000;

printf("\nDifference : %d",ptr2-ptr1);

//Output :
//Difference : 250

لطفا در صورت امکان با یک مثال کاربرد دقیق

(float یا char یا int یا... *)  

را مشخص کنید

* مخصوصا علامت

تشکر


یکشنبه، ۲ اسفند ماه ۱۳۹۴، ساعت ۲۱:۵۴
مسعود:
* type یعنی اشاره‌گر به حافظه‌ای که مقدار داخل اون از نوع type در نظر گرفته می‌شه. حالا اگه type مثلا k بایتی باشه، اشاره‌گر به اولین خونه اشاره می‌کنه و k - 1 خونه‌ی بعدی رو هم به عنوان بخشی از این متغیر در نظر می‌گیره.
مثال اول ptr اشاره‌گر به نوع int (دو بایتی) با آدرس 1000 تعریف شده. پس وقتی با یک جمع می‌شه مقدار اون از 1000 به  1002 افزایش پیدا می‌کنه. به بیان دیگه از نظر اشاره‌گر int حافظه‌ی 1000 و 1001 مربوط به یه متغیر هستن و وقتی با یک جمع می‌شه از روی 1001 می‌پره تا به متغیر بعدی برسه. به همین ترتیب double چهار بایتی ...
در مورد مثال سوم هم حساب کرده که از حافظه‌ی شماره‌ی 1000 تا 2000 چند تا float چهار بایتی ممکنه وجود داشته باشه که طبیعتا 250 تا هست. در واقع اگه ptr1 رو 250 بار با یک جمع بزنید، چهار گام چهار گام جلو می‌ره تا به 2000 می‌رسه.

» صادق

دوشنبه، ۳ اسفند ماه ۱۳۹۴، ساعت ۰۱:۳۳
سلام

از توضیحات شما سپاسگزارم و الان دقیقا متوجه حقیقت امر شدم

فقط اینکه در مثال 3

ptr2+ptr1 چرا وقتی

ptr2-ptr1 را بجای

مینوسیم، برنامه با خطا زیر روبه رو میشود

error: invalid operands to binary + (have 'float *' and 'float *')|


دوشنبه، ۳ اسفند ماه ۱۳۹۴، ساعت ۱۶:۳۲
مسعود:
عملگر جمع برای دو اشاره‌گر تعریف نشده. شما می‌تونید مثل مثال‌های قبلی اشاره‌گر رو با یک عدد صحیح جمع یا منها کنید تا به تعداد گام‌هایی که مشخص کردید جلو یا عقب بره. اما جمع دو نشانی با هم معنایی نداره. مثل اینکه بگید پلاک ۱۵ رو با پلاک ۱۳ جمع بزنیم. مسلما همچین چیزی معنا نداره. ولی می‌شه پلاک ۱۵ رو ۱۳ واحد جلو برد و به پلاک ۲۸ رسید.
تفریق دو اشاره‌گر هم فاصله‌ی اونها رو مثل مثالی که خودتون آوردید نشون می‌ده و یک عدد صحیح هست.

» صادق

دوشنبه، ۳ اسفند ماه ۱۳۹۴، ساعت ۱۷:۲۰
سلام

از توضیحات شما سپاسگزارم

» صادق

جمعه، ۱۴ اسفند ماه ۱۳۹۴، ساعت ۰۵:۰۷
سلام

مفهموم دو خط زیر چیست؟

#define RX_DESC_BASE        0x20080000

#define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE  +8*i))

تشکر


شنبه، ۱۵ اسفند ماه ۱۳۹۴، ساعت ۲۲:۴۹
مسعود:
اینجا از ابزار ماکرو استفاده شده.
سطر اول یه آدرس رو به عبارت RX_DESC_BASE ربط داده و سطر دوم مثل تابعی هست که با دریافت مقدار i عبارت مقابلش رو محاسبه می‌کنه. روش محاسبه هم قبلا در پاسخ‌ها اشاره کردم که چطور هست.

» مهدی

شنبه، ۱۲ تیر ماه ۱۳۹۵، ساعت ۱۲:۱۳
با سلام  
خیلی ممنون از سایت خوبتون

» ............

سه‌شنبه، ۱۲ مرداد ماه ۱۳۹۵، ساعت ۱۴:۴۶
خیلی خوب بود توضیحات

» saba

شنبه، ۲۹ آبان ماه ۱۳۹۵، ساعت ۲۲:۴۵
خیلی خوب من که هیچی از اشاره گرها نمیدونستم کاملا متوجه شدم و فهمیدم!

» فاطمه

جمعه، ۱۹ آذر ماه ۱۳۹۵، ساعت ۱۳:۲۶
سلام. میشه ی مثال کاربردی و طولانی از pointer بزنید.. ممنون میشم

» sajjad

سه‌شنبه، ۱۴ دی ماه ۱۳۹۵، ساعت ۱۳:۱۶
سلام خسته نباشید
خواستم ببینم اگه بخوایم متنی رو نمایش بدیم که خودش گیومه داشته باشه "برای مثل"اینجوری "" دیباگر errorمیده خواستم ببینم با چه روشی میشه این متن رو نمایش داد با cout


چهارشنبه، ۱۵ دی ماه ۱۳۹۵، ساعت ۱۳:۵۸
مسعود:
سلام
به جای " از "\ استفاده کنید.

» AmirReza

جمعه، ۱۷ دی ماه ۱۳۹۵، ساعت ۱۸:۳۹
سلاااااااااام
ناموووووسن عالی بود !!!
مسعود عزیزی که با قلم روانت عالی توضیح دادی !! خیلی مرسی ازت
0606060606


جمعه، ۱۷ دی ماه ۱۳۹۵، ساعت ۲۲:۴۸
مسعود:
سلام
خواهش می‌کنم. خوشحالم که نوشته براتون مفید بوده. 01

» ++programing c

پنجشنبه، ۱۸ آبان ماه ۱۳۹۶، ساعت ۱۴:۴۳
درمورد سوال اینکه چجوری متغیری تعریف کنیم که در زیر برنامه ای مثه تابع اصلی ++c یعنی main
هم بتونیم دوباره تعریفش کنیم هم آخرین مقدار خودشو حفظ کنه باید از کلاس ذخیره سازی externبرای تعریف کردن متغیر برای مقدار دهی و از کلاس ذخیره سازی staticبرای حفظ کردن آخرین مقدار متغیر به این صورت البته امتحان نکردم که میشه دوتارو بکار برد یا نه
میتونید امتحان کنید به این صورت
()int main
{
;extern static int x=10
}