Skip to content

Commit 1818baa

Browse files
committed
Update Structure questions
1 parent 56c1edd commit 1818baa

File tree

4 files changed

+945
-1
lines changed

4 files changed

+945
-1
lines changed
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
2+
<div dir="rtl">
3+
4+
# آموزش Alignment و Padding در C: از پایه تا پیشرفته با سناریوهای کاربردی
5+
6+
در زبان C، وقتی از `struct` استفاده می‌کنیم، موضوعاتی مثل Alignment (تراز کردن) و Padding (پُر کردن) اهمیت زیادی پیدا می‌کند. این مفاهیم تعیین می‌کنند که داده‌ها چطور در حافظه ذخیره می‌شوند و چطور به آن‌ها دسترسی پیدا می‌کنیم. در این مقاله، با استفاده از سناریوهای کاربردی، مفاهیم Alignment و Padding را به شکل کامل بررسی می‌کنیم. همچنین با استفاده از شکل‌هایی که با کاراکترهای متنی ساخته می‌شوند، سعی می‌کنیم این مفاهیم را به ساده‌ترین شکل ممکن توضیح دهیم.
7+
8+
## 1. مفهوم Alignment
9+
10+
در زبان C، داده‌ها باید به شکلی در حافظه ذخیره شوند که دسترسی به آن‌ها سریع و بهینه باشد. Alignment به این معناست که هر داده باید در آدرس حافظه‌ای ذخیره شود که با اندازه خودش هماهنگ باشد. مثلاً، یک داده `int` که معمولاً 4 بایت است، بهتر است در آدرسی ذخیره شود که مضربی از 4 باشد. این کار باعث می‌شود پردازنده بتواند داده را به شکل بهینه‌تری بخواند.
11+
12+
### 1.1 علت وجود Alignment
13+
14+
علت اصلی وجود Alignment به معماری پردازنده و سرعت دسترسی به داده‌ها برمی‌گردد. پردازنده‌ها معمولاً داده‌ها را در واحدهای مشخص (مثل 4 بایت یا 8 بایت) می‌خوانند. اگر داده‌ها در آدرسی ذخیره شوند که با این واحدها هماهنگ نباشد (مثلاً یک داده 4 بایتی در آدرسی که مضربی از 4 نیست)، پردازنده باید داده را به صورت چند تکه بخواند و دوباره آن را سرهم کند که این کار باعث کاهش سرعت می‌شود.
15+
16+
### سناریو 1: درک Alignment با یک مثال ساده
17+
18+
فرض کن یک `struct` داری که شامل دو متغیر است: یکی `char` و یکی `int`. در حالت عادی، انتظار داری که `struct` به اندازه جمع اندازه‌های این دو متغیر باشد، ولی به خاطر Alignment این اتفاق نمی‌افتد.
19+
20+
<div dir="ltr">
21+
22+
```c
23+
#include <stdio.h>
24+
25+
typedef struct {
26+
char c;
27+
int i;
28+
} MyStruct;
29+
30+
int main() {
31+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
32+
return 0;
33+
}
34+
```
35+
</div>
36+
37+
38+
#### توضیح
39+
40+
در این مثال، `char` یک بایت و `int` چهار بایت فضا می‌گیرد. ولی وقتی سایز `struct` را چک می‌کنی، می‌بینی که اندازه آن به جای 5 بایت، 8 بایت است. چرا؟ به خاطر Alignment.
41+
42+
#### تصویرسازی Alignment
43+
44+
حالا ببینیم این `struct` چطور در حافظه ذخیره می‌شود:
45+
<div dir="ltr">
46+
47+
```
48+
Memory Layout: | c (1 byte) | Padding (3 bytes) | i (4 bytes) |
49+
```
50+
</div>
51+
52+
اینجا به این دلیل که `int` باید در آدرسی ذخیره شود که مضربی از 4 باشد، سه بایت بعد از `char` برای پُر کردن اضافه می‌شوند.
53+
54+
## 2. مفهوم Padding
55+
56+
Padding به معنی اضافه کردن بایت‌های خالی (ناخواسته) به `struct` است تا داده‌ها به درستی تراز شوند. این بایت‌های خالی به طور خودکار توسط کامپایلر اضافه می‌شوند تا مطمئن شود که هر فیلد در یک آدرس بهینه در حافظه قرار دارد.
57+
58+
### سناریو 2: درک Padding با تغییر ترتیب متغیرها
59+
60+
حالا بیایم ترتیب متغیرهای `struct` را تغییر دهیم و ببینیم چه اتفاقی می‌افتد. اگر `int` را اول و `char` را دوم قرار دهیم، Padding چطور تغییر می‌کند؟
61+
62+
<div dir="ltr">
63+
64+
```c
65+
#include <stdio.h>
66+
67+
typedef struct {
68+
int i;
69+
char c;
70+
} MyStruct;
71+
72+
int main() {
73+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
74+
return 0;
75+
}
76+
```
77+
</div>
78+
79+
80+
#### توضیح
81+
82+
این بار، `int` اول قرار دارد و `char` بعد از آن می‌آید. چون `int` به درستی تراز شده، هیچ Padding قبل از آن اضافه نمی‌شود. اما بعد از `char`، 3 بایت Padding اضافه می‌شود تا ساختار به درستی تراز شود.
83+
84+
#### تصویرسازی Padding
85+
<div dir="ltr">
86+
87+
```
88+
Memory Layout: | i (4 bytes) | c (1 byte) | Padding (3 bytes) |
89+
```
90+
</div>
91+
92+
## 3. بهینه‌سازی Alignment و Padding
93+
94+
گاهی اوقات می‌توان با تغییر ترتیب فیلدها در `struct`، فضای حافظه را بهینه‌تر کرد و از Padding غیرضروری جلوگیری کرد.
95+
96+
### سناریو 3: بهینه‌سازی فضای حافظه با تغییر ترتیب فیلدها
97+
98+
فرض کن یک `struct` داری که شامل یک `char`، یک `int` و یک `double` است. اگر این فیلدها را به ترتیب زیر بچینی، چه اتفاقی می‌افتد؟
99+
100+
<div dir="ltr">
101+
102+
```c
103+
#include <stdio.h>
104+
105+
typedef struct {
106+
char c;
107+
int i;
108+
double d;
109+
} MyStruct;
110+
111+
int main() {
112+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
113+
return 0;
114+
}
115+
```
116+
</div>
117+
118+
119+
#### توضیح
120+
121+
در این حالت، `char` و `int` هر دو نیاز به Padding دارند. اما اگر ترتیب فیلدها را تغییر دهیم تا ابتدا بزرگ‌ترین فیلد (`double`) قرار بگیرد، می‌توانیم از Padding جلوگیری کنیم.
122+
123+
#### بهینه‌سازی
124+
125+
حالا ببینیم چطور با تغییر ترتیب فیلدها می‌توانیم فضای حافظه را بهینه کنیم:
126+
127+
<div dir="ltr">
128+
129+
```c
130+
#include <stdio.h>
131+
132+
typedef struct {
133+
double d;
134+
int i;
135+
char c;
136+
} MyStruct;
137+
138+
int main() {
139+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
140+
return 0;
141+
}
142+
```
143+
</div>
144+
145+
146+
#### تصویرسازی بهینه‌سازی
147+
<div dir="ltr">
148+
149+
```
150+
Memory Layout (بهینه‌سازی شده): | d (8 bytes) | i (4 bytes) | c (1 byte) | Padding (3 bytes) |
151+
152+
```
153+
</div>
154+
155+
در این حالت، فضای Padding کمتر و حافظه بهینه‌تر شده است.
156+
157+
158+
## 4. استفاده از #pragma و __attribute__ برای کنترل Alignment و Padding
159+
160+
در بعضی مواقع، نیاز داریم که کنترل بیشتری روی Alignment و Padding داشته باشیم. در چنین شرایطی می‌توانیم از `#pragma pack` یا `__attribute__ ((packed))` استفاده کنیم.
161+
162+
### 4.1 استفاده از `#pragma pack`
163+
164+
`#pragma pack` به ما اجازه می‌دهد که اندازه Alignment را تنظیم کنیم و از Padding اضافی جلوگیری کنیم. به عنوان مثال، اگر بخواهیم هیچ Padding بین فیلدهای یک `struct` وجود نداشته باشد، می‌توانیم از `#pragma pack(1)` استفاده کنیم:
165+
166+
<div dir="ltr">
167+
168+
```c
169+
#include <stdio.h>
170+
171+
#pragma pack(1)
172+
typedef struct {
173+
char c;
174+
int i;
175+
double d;
176+
} MyStruct;
177+
178+
int main() {
179+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
180+
return 0;
181+
}
182+
```
183+
</div>
184+
185+
186+
#### توضیح
187+
188+
با استفاده از `#pragma pack(1)`، کامپایلر را مجبور می‌کنیم که هیچ Padding بین فیلدها اضافه نکند. این باعث می‌شود که سایز `struct` دقیقاً برابر با جمع اندازه‌های فیلدها باشد.
189+
190+
### 4.2 استفاده از `__attribute__ ((packed))`
191+
192+
`__attribute__ ((packed))` نیز به ما اجازه می‌دهد که یک `struct` را بدون Padding تعریف کنیم:
193+
194+
<div dir="ltr">
195+
196+
```c
197+
#include <stdio.h>
198+
199+
typedef struct {
200+
char c;
201+
int i;
202+
double d;
203+
} __attribute__ ((packed)) MyStruct;
204+
205+
int main() {
206+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
207+
return 0;
208+
}
209+
```
210+
</div>
211+
212+
213+
#### توضیح
214+
215+
در این مثال، با استفاده از `__attribute__ ((packed))`، از اضافه شدن Padding به `struct` جلوگیری می‌کنیم.
216+
217+
## 5. ترکیب Alignment و Padding با Union
218+
219+
گاهی اوقات از `union` استفاده می‌کنیم تا داده‌های مختلف را در یک فضای حافظه نگه داریم. وقتی `union` با `struct` ترکیب شود، Alignment و Padding همچنان اهمیت دارند.
220+
221+
### 5.1 سناریو: درک ترکیب Alignment و Padding با Union
222+
223+
فرض کن یک `union` داری که شامل یک `int` و یک `char` است. اگر این `union` را داخل یک `struct` قرار دهیم که خودش هم شامل یک `double` است، چه اتفاقی می‌افتد؟
224+
225+
<div dir="ltr">
226+
227+
```c
228+
#include <stdio.h>
229+
230+
typedef union {
231+
int i;
232+
char c;
233+
} MyUnion;
234+
235+
typedef struct {
236+
double d;
237+
MyUnion u;
238+
} MyStruct;
239+
240+
int main() {
241+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
242+
return 0;
243+
}
244+
```
245+
</div>
246+
247+
248+
#### توضیح
249+
250+
در این حالت، `double` به درستی تراز شده است. اما چون `union` شامل `int` است، `union` هم باید به درستی تراز شود. این به معنی اضافه شدن Padding قبل از `union` است.
251+
252+
#### تصویرسازی ترکیب
253+
<div dir="ltr">
254+
255+
```
256+
Memory Layout: | d (8 bytes) | Padding (4 bytes) | u (4 bytes) |
257+
```
258+
</div>
259+
260+
## 6. ترکیب Alignment و Padding با آرایه‌ها
261+
262+
وقتی `struct` ها را به صورت آرایه تعریف می‌کنیم، Padding و Alignment همچنان اهمیت دارند.
263+
264+
### 6.1 سناریو: درک ترکیب Alignment و Padding با آرایه‌ها
265+
266+
فرض کن یک `struct` داری که شامل یک `char` و یک `int` است. حالا این `struct` را به صورت آرایه تعریف می‌کنیم:
267+
268+
<div dir="ltr">
269+
270+
```c
271+
#include <stdio.h>
272+
273+
typedef struct {
274+
char c;
275+
int i;
276+
} MyStruct;
277+
278+
int main() {
279+
MyStruct arr[3];
280+
printf("Size of MyStruct: %lu\n", sizeof(MyStruct));
281+
printf("Size of array: %lu\n", sizeof(arr));
282+
return 0;
283+
}
284+
```
285+
</div>
286+
287+
288+
#### توضیح
289+
290+
هر عنصر از آرایه باید به درستی تراز شود، بنابراین Padding بعد از هر عنصر اضافه می‌شود تا عنصر بعدی نیز به درستی تراز شود.
291+
292+
#### تصویرسازی ترکیب
293+
<div dir="ltr">
294+
295+
```
296+
Memory Layout: | c (1 byte) | Padding (3 bytes) | i (4 bytes) | <- Element 1 | c (1 byte) | Padding (3 bytes) | i (4 bytes) | <- Element 2 | c (1 byte) | Padding (3 bytes) | i (4 bytes) | <- Element 3
297+
```
298+
</div>
299+
300+
## 7. جمع‌بندی
301+
302+
در این مقاله، با مفاهیم Alignment و Padding آشنا شدیم و دیدیم که چطور می‌توانیم با تغییر ترتیب فیلدها در `struct` و ترکیب آن با `union` و `array`، فضای حافظه را بهینه‌تر کنیم. همچنین با استفاده از `#pragma pack` و `__attribute__ ((packed))` می‌توانیم کنترل بیشتری بر روی Padding داشته باشیم. استفاده از این تکنیک‌ها می‌تواند به بهینه‌تر شدن برنامه‌ها و کاهش مصرف حافظه منجر شود.
303+
304+
## تمرین‌ها
305+
306+
307+
| شماره | سوال | بارم |
308+
|-------|------|------|
309+
| 1 | یک `struct` بساز که شامل یک `short`، یک `char` و یک `int` باشد. سایز این `struct` را محاسبه کن و دلیل وجود Padding را توضیح بده. | 3 |
310+
| 2 | ساختار زیر را بهینه کن تا کمترین فضای حافظه را مصرف کند: `struct { char c; double d; int i; }`. | 4 |
311+
| 3 | یک `union` بساز که شامل یک `int`، یک `float` و یک `char` باشد. این `union` را داخل یک `struct` قرار بده و بررسی کن که چطور Alignment و Padding روی اندازه کلی `struct` تأثیر می‌گذارند. | 5 |
312+
| 4 | برنامه‌ای بنویس که سایز `struct` و `union` را در شرایط مختلف (با و بدون Padding) مقایسه کند. | 4 |
313+
| 5 | از `#pragma pack` و `__attribute__ ((packed))` برای حذف Padding استفاده کن و بررسی کن که چطور این کار روی عملکرد برنامه تأثیر می‌گذارد. | 5 |
314+
315+
</div>

Questions/Structures/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<div dir="rtl">
2+
3+
# آموزش structure در زبان C
4+
5+
این مجموعه شامل مقالات و تمرین‌های مختلف در زمینه `STRUCTURE` و `ALIGNMENT` در زبان C است که به شما کمک می‌کند تا این مفاهیم را به صورت جامع و عملی در پروژه‌های نرم‌افزاری خود پیاده‌سازی کنید.
6+
7+
## فهرست مقالات
8+
9+
1. [آموزش Structure در C](./Structures.md)
10+
- **توضیحات:** این مقاله به شما آموزش می‌دهد که چگونه از `STRUCTURE` برای سازماندهی داده‌ها در برنامه‌های C استفاده کنید. شامل مباحث پایه‌ای تا پیشرفته از جمله ترکیب `STRUCTURE` با `UNION` و `ENUM`.
11+
- **تمرین‌ها:** شامل تمرین‌هایی برای پیاده‌سازی و مدیریت `STRUCTURE` ها در پروژه‌های مختلف.
12+
13+
2. [آموزش Alignment و Padding در C](./PaddingAndAlignment.md)
14+
- **توضیحات:** در این مقاله با مفاهیم `ALIGNMENT` و `PADDING` آشنا می‌شوید و یاد می‌گیرید که چطور از این مفاهیم برای بهینه‌سازی حافظه و بهبود عملکرد برنامه‌ها استفاده کنید.
15+
- **تمرین‌ها:** تمرین‌هایی برای درک بهتر `ALIGNMENT` و `PADDING`، بهینه‌سازی ساختارها و استفاده از `#pragma` و `__attribute__`.
16+
17+
## چطور استفاده کنیم؟
18+
19+
1. **مطالعه مقالات:** ابتدا مقاله مربوط به هر مبحث را مطالعه کنید تا با مفاهیم و کاربردهای آن آشنا شوید.
20+
2. **انجام تمرین‌ها:** پس از مطالعه، به تمرین‌های موجود در هر مقاله مراجعه کرده و آن‌ها را پیاده‌سازی کنید.
21+
3. **بهبود مهارت‌ها:** با پیاده‌سازی این مفاهیم در پروژه‌های واقعی، مهارت خود را در برنامه‌نویسی C بهبود دهید.
22+
23+
## چرا STRUCTURE و ALIGNMENT؟
24+
25+
این مفاهیم به شما کمک می‌کنند تا:
26+
- **کدهای خود را مرتب‌تر و سازمان‌یافته‌تر کنید.**
27+
- **داده‌های مختلف را به شکل موثرتری در حافظه مدیریت کنید.**
28+
- **برنامه‌هایی با عملکرد بهتر و مصرف حافظه بهینه‌تر بنویسید.**
29+
30+
## مشارکت
31+
32+
اگر علاقه‌مندید که به این پروژه کمک کنید یا تمرین‌های جدیدی پیشنهاد دهید، می‌توانید با ما تماس بگیرید یا درخواست‌های خود را از طریق [GitHub Issues](#) ارسال کنید.
33+
34+
## لایسنس
35+
36+
این پروژه تحت لایسنس MIT منتشر شده است. برای اطلاعات بیشتر به فایل [LICENSE](./LICENSE) مراجعه کنید.
37+
38+
</div>

0 commit comments

Comments
 (0)