برای اینکه آخرین کاراکتر یک آرایه را چاپ کنیم چه کار میکنم ؟
char name[] = "Virgool it's trouble for showing code"; size_t length = strlen(name); printf("%c\n", name[length - 1]);
خب به نظرم این روش زیاد جالبی نیست، چرا که برای اینکار نیاز به glibc یا musl و یا هر libc دیگه ای پیدا میکنیم. و کاری هم که این کتابخونه ها میکنند اینه :
size_t strlen(const char *s) { const char *a = s; for (; *s; s++); return s-a; }
این سورس از musl هست، و میبینید که برای پیدا کردن طول از یک حلقه استفاده کرده.
اما یک کار دیگر هم میتوان کرد، قبول دارید که میشه آدرس کل آرایه را گرفت و منهای یکی کرد و آخرین خونه آرایه را به دست آورد ؟ خب بیاید انجام بدیم :
char name[] = "Virgool it's trouble for showing code"; printf("%c\n", *((char*)(&name + 1) - 2));
به همین راحتی میتونیم آخرین خونه آرایه را به دست بیاریم. اینجا name& به ما آدرس کل آرایه را میده، هرچند که خود name هم آدرس کل آرایه را میده اما فرقش اینکه name به خونه اول اشاره میکنه اما name& به کل آرایه، پس اگه بگیم name + 1& یعنی آدرس کل آرایه به علاوه یک که میشه یکی بعد از آخرین خونه آرایه، حالا برای اینکه ما بگیم که آدرس خونه قبلی را میخوایم اگه حالت ساده منهای دو کنیم:
*((&name + 1) - 2)
که خب برگشتیم سر جای اولمون، چرا که اون name& به کل آرایه اشاره میکرد باید این نوع اشاره کردن را عوض کنیم و بگیم که تبدیل کن به *char و اینطوری به اندازه یک char برمیگرده عقب. مورد دیگه دقت کنید که شما برای رشته ها باید منهای دو کنید چرا که آخرین کاراکتر null terminator هست در واقع.
به این روش هم میتونید بدون استفاده از عملگر sizeof طول آرایه را حساب کنید به اینصورت :
size_t length = *(&name + 1) - name;
که اختلاف را به دست میاره. البته طبق C99 §6.5.2.1/2 (صفحه ۸۲) میدونید که E1[E2] برابر هست با
(*((E1)+(E2)))
پس بهتره که اینطوری بنویسیم :
size_t length = (&name)[1] - name;
برای اینکه یه بهبودی به کدمون بدیم، میتونیم در قالب یک ماکرو هم پیاده کنیم :
#include <stdio.h> #define last(array, index, type) \ (* ((type*)(&array + 1) - index)) int main () { int int_array[] = {1, 2, 3, 4}; char char_array[] = "something is here"; printf("%d\n", last(int_array, 1, int)); printf("%c\n", last(char_array, 2, char)); return 0 }