یک آرایه چهارتایی از عدد صحیح. در تابع اصلی، sizeof عدد ۱۶ میدهد، یعنی چهار خانه چهاربایتی. همان آرایه را به یک تابع پاس دهید و داخل آن تابع همان عملگر عدد ۸ میدهد.
اندازهگیریشده با Apple clang 21.0.0 در تاریخ ۲۰۲۶-۰۹-۰۳. عدد ۸ اندازه آرایه نیست، اندازه یک اشارهگر است. آرایه هنگام پاس دادن به اشارهگر به اولین عضوش تبدیل میشود و طول را همانجا جا میگذارد.
نتیجهای که از این میآید یک قاعده است و استثنا هم ندارد: هر تابعی در سی که آرایه میگیرد، باید یک شمارنده هم کنارش بگیرد. هیچ راهی برای بازیابی طول از خود اشارهگر وجود ندارد.
حساب اشارهگر با واحد نوع کار میکند
افزودن یک به یک اشارهگر، آدرس را به اندازه یک عضو جلو میبرد و نه یک بایت. با sizeof(int) برابر ۴، فاصله دو خانه پشت سر هم ۴ بایت است. برای همین p + 1 روی یک اشارهگر به عدد صحیح چهار بایت جلو میرود و روی اشارهگر به یک ساختار بزرگتر، به اندازه همان ساختار.
و به همین دلیل نوع اشارهگر مهم است حتی وقتی فقط آدرس را جابهجا میکنید: تبدیل نوع یک اشارهگر، معنای حساب رویش را عوض میکند و همان جایی است که خطاهای خواندن یک خانه جلوتر یا عقبتر ساخته میشوند.
سه حالتی که مقدارها در آنها زندگی میکنند
متغیر محلی روی پشته است و با برگشتن تابع از بین میرود؛ برگرداندن آدرس یک متغیر محلی، آدرسی میدهد که دیگر مال کسی نیست. متغیر ایستا و سراسری تا پایان برنامه زندهاند. و هرچه با تخصیص پویا گرفته شود تا وقتی خودتان آزادش نکنید میماند.
سه خطای مربوط به حالت سوم، همه بیصدا: آزاد نکردن، که نشت است؛ آزاد کردن دو باره؛ و استفاده پس از آزادسازی. نکتهای که در آزمایش دیده میشود این است که پس از free خود اشارهگر همچنان همان عدد را دارد و تهی نمیشود، پس هیچ بررسیای متوجه نمیشود. عادتی که این را میگیرد یک سطر است: بلافاصله پس از آزادسازی، اشارهگر را تهی کنید. همان کلاس خطاها از دید زبان در مقدارها کجا مینشینند و چه وقت آزاد میشوند دیده میشود.
جایی که کار گیر میکند، تمرینهای بدون ابزار است
در درسهای فارسی، اشارهگر معمولا با تمرینهای کاغذی و نمودار جعبه و فلش آموزش داده میشود و هیچوقت کسی برنامه را زیر یک ابزار بررسی حافظه اجرا نمیکند. نتیجهاش این است که آدم مفهوم را میفهمد و خطاهایش را نمیبیند، چون برنامههای تمرینی کوچکاند و خطای حافظه در آنها معمولا هیچ اثری ندارد. تفاوت واقعی از جایی شروع میشود که همان تمرین را با ضدعفونیکننده آدرس بسازید: خطایی که تا دیروز هیچ نشانهای نداشت، حالا با نام فایل و شماره سطر میایستد.
ابزار، و سالی که این حرف درست است
در سال ۲۰۲۶ ضدعفونیکننده آدرس همراه خود clang میآید، رایگان است و به شبکه نیاز ندارد؛ با یک پرچم هنگام ساخت روشن میشود و جای valgrind را برای بیشتر کارها گرفته، چون دهها برابر سریعتر است و روی مک بهمراتب بهتر کار میکند. برای پیدا کردن نشتی، ضدعفونیکننده نشت هم در همان بسته است. هیچکدام رفتار برنامه را عوض نمیکنند و فقط کندش میکنند، پس در ساخت اشکالزدایی روشن و در ساخت نهایی خاموشاند.
پرسش بعدی این است که چرا کامپایلر در برابر این خطاها ساکت است و چه چیزی را اصلا تضمین میکند، که نزدیک به ماشین، و هیچ چیز پنهان نیست جوابش را دارد. و زبانی که همین سه خطا را در زمان کامپایل رد میکند در ایمنی حافظه، بدون جمعکننده زباله است.