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

مفهوم و کاربردها همراه با مثال

✤    ۳۰ شهریور ۱۳۸۵ - آخرین به‌روزرسانی: ۱۱ خرداد ۱۳۸۸

یکی از مهمترین مباحث کاربردی هر زبان برنامه‌نویسی، اشاره‌گر و مفهوم آن است که کاربرد گسترده‌ای در شاخه ساختمان داده‌ها نیز دارد. در این فرصت با مفهوم اشاره‌گر و همینطور روش تعریف آن در زبان ++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;

    swap(&m, &n);

    cout << "m = " << m << " , n = " << n;

}

  

به جای محتویات متغیرهای 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 قرار می‌گیرد.


نسخه‌ی اولیه‌ی این نوشته از وبلاگ برنامه‌نویسی و طراحی الگوریتم به الگوریتمستان منتقل شده است.

تا کنون ۱۲۲ امتیاز ثبت شده
نوشته لایک نداشت؟
 
به اشتراک گذاری نوشته

amasoudfam.ir/l/zw2y1

اشتراک‌گذاری در LinkedIn     اشتراک‌گذاری در Twitter     ارسال با Telegram

نام: *  
پست الکترونیک (محرمانه):
پیام: *  
• روزبه
۲۱ آبان ۱۳۸۵، ساعت ۰۳:۰۹

سلام .

ما همیشه به یاد دوستان هستم . چون یه مدتی نبودید و من نیز گیر درسام بودم این جدایی برای مدتی پیش ائمد .

امیدوارم که دیگه این اتفاق نیفته .

تا دیدار بعد روزبه .

• fatemeh
۲۵ خرداد ۱۳۸۶، ساعت ۰۰:۲۷

salam

vaghean site khubi darino kheili mofide.man ke kheili chiza azatun yad gereftam.

moafagh bashin

• shahryar
۱ تیر ۱۳۸۶، ساعت ۰۶:۵۴

با سلام

میخواستم بدونم شما  درمورد برنامه های محاسباتی از طریق مفاهیم اشاره گرها در شی گرایی میتونید به من کمک کنید . مقاله, سایت,...

ممنون

• حامد
۲۷ تیر ۱۳۸۶، ساعت ۰۳:۰۵

سلام

واقعا دستت درد نکنه

من تو این مسئله اشاره گر ها مونده بودم واقعا به من کمک کرد .

• رضا
۱۲ خرداد ۱۳۸۷، ساعت ۰۹:۲۰

با سلام وتشکر از سایت بسیار مفیدتون من دانشجوی کامپیوترم و پروژه پایان ترمم در مورد garbage collector است اگه میشه راهنماییم کنید که چکار کنم

• نجمه
۵ فروردین ۱۳۸۸، ساعت ۰۹:۱۱

با سلام

می خواستم بدونم اشاره گرها چه کاربردی در  صنعت نرم افزار داشتن؟

مسعود اقدسی‌فام
۲۶ فروردین ۱۳۸۸، ساعت ۲۲:۲۶

سلام نجمه خانم

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

• جلال
۳۱ فروردین ۱۳۸۸، ساعت ۱۸:۲۰

سلام

ممنون از مطالب خوبتون

يه سوالم داشتم ، چطوري با استفاده از اشاره گر ها روش هاي مرتب سازي رو ميشه پياده كرد ممنون

مسعود اقدسی‌فام
۳۱ فروردین ۱۳۸۸، ساعت ۲۰:۰۱

سلام جلال جان

ممنون از محبتتون.

استفاده از اشاره گرها برای مرتب سازی داده های بزرگ (مثل ساختارهای پیچیده یا ساختمانها) این مزیت رو داره که باعث کاهش تبادل اطلاعات می شه. لازم نیست هر بار دو داده چند ده بایتی رو جابجا کنید. کافیه آدرس حافظه های اونها رو با هم جابحا کنید. به عبارت ساده تر، به جای آرایه ای از داده ها، آرایه ای از اشاره گرها به داده ها رو بر اساس محلی که بهش اشاره می کنن مرتب می کنید.

• محمد
۹ دی ۱۳۸۸، ساعت ۱۶:۲۱

چطور میشه آرایه پویای چند بعدی تعریف کرد؟

۹ دی ۱۳۸۸، ساعت ۱۷:۵۹
• مسعود اقدسی‌فام

از چه بعدی مد نظرته محمد جان؟

• فرهاد
۹ فروردین ۱۳۸۹، ساعت ۱۶:۳۱

لطفا برنامه ی یک ماشین حساب ساده با جمع و ضرب و تقسیم و توان و سینوس و کسینوس و 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

}

• میلاد
۲۰ فروردین ۱۳۹۷، ساعت ۰۹:۰۹

عالی بود حال کردم

• رضا
۱۰ مرداد ۱۳۹۷، ساعت ۱۵:۱۵

آقا فقط  یک کلمه، عالی بود 06

• مارش
۲۷ مهر ۱۳۹۷، ساعت ۱۸:۵۹

دوستان لطف می کنید معنی اصطلاح differencing رو برای من توضیح بدید. خیلی ممنون

• صدرا حکیم
۲۸ آذر ۱۳۹۷، ساعت ۱۹:۴۰

سلام خسته نباشید

در این جمله ( بخش اخر در عملیات ریاضی ) :

" متغیر c یک اشاره‌گر به عدد صحیح بزرگ است. زمانی که آن را با عدد یک جمع می‌زنیم "

منظورتون از از "آن" همون متغیر b هست یا متغیر c ؟ چون اینجا متغیر b رو با یک جمع زدیم.

الان در واقع اینطوری میشه :

وقتی c رو برابر با b + 1 میزاریم چون c، چهار بایت ذخیره میکنه، پس اون 1 در واقع 4 حساب میشه و 4 تا به b اضافه میشه.

ممنون

• موسوی
۱۰ تیر ۱۳۹۸، ساعت ۰۰:۰۰

سلام ببخشید کسی میتواند این ببرنامه را بنویسید؟

با استفاده از اشاره گرها تابعی بنویسید که ضمن انتخاب نوع عمل ریاضی دو عدد را از ورودی گرفته و نتایج را بر اساس نوع عمل ریاضی به خروجی بفرستد

• موسوی
۱۰ تیر ۱۳۹۸، ساعت ۱۲:۰۷

سلام ببخشید کسی میتواند این ببرنامه را بنویسید؟

با استفاده از اشاره گرها تابعی بنویسید که ضمن انتخاب نوع عمل ریاضی دو عدد را از ورودی گرفته و نتایج را بر اساس نوع عمل ریاضی به خروجی بفرستد

• سعید
۸ فروردین ۱۳۹۹، ساعت ۰۱:۰۴

عالی بود

• سعید
۱۴ فروردین ۱۳۹۹، ساعت ۱۴:۲۸

عالی بود

• ایمانزاده
۱۳ آبان ۱۳۹۹، ساعت ۱۷:۱۶

سلام وقتتون بخیر . چرا یک پوینتر اینتیجری را وقتی ++ میکنیم چهار خانه جهش میکند؟

• mehdy
۲۸ شهریور ۱۴۰۰، ساعت ۰۰:۳۸

char *str[5];

for(int i=0;i<5;i++)

           cin>>*(str + i);

سلام من میخوام که یه ارایه اشاره گر رشته ای رو ایجاد و مقدار دهی کنم اما خطا میده

چطوری باید مقدار دهی کنم