Hãy nhìn vào hai chức năng:Trình tự phân bổ biến cục bộ trên stack
void function1() {
int x;
int y;
int z;
int *ret;
}
void function2() {
char buffer1[4];
char buffer2[4];
char buffer3[4];
int *ret;
}
Nếu tôi phá vỡ tại function1()
trong gdb
, và in các địa chỉ của các biến, tôi có được điều này:
(gdb) p &x
$1 = (int *) 0xbffff380
(gdb) p &y
$2 = (int *) 0xbffff384
(gdb) p &z
$3 = (int *) 0xbffff388
(gdb) p &ret
$4 = (int **) 0xbffff38c
Nếu tôi làm điều tương tự tại function2()
, tôi có được điều này:
(gdb) p &buffer1
$1 = (char (*)[4]) 0xbffff388
(gdb) p &buffer2
$2 = (char (*)[4]) 0xbffff384
(gdb) p &buffer3
$3 = (char (*)[4]) 0xbffff380
(gdb) p &ret
$4 = (int **) 0xbffff38c
Bạn sẽ nhận thấy rằng trong cả hai chức năng, ret
được lưu trữ gần nhất trên cùng của ngăn xếp. Trong function1()
, tiếp theo là z
, y
và cuối cùng là x
. Trong function2()
, ret
được theo sau bởi buffer1
, sau đó buffer2
và buffer3
. Tại sao lệnh lưu trữ thay đổi? Chúng tôi đang sử dụng cùng một lượng bộ nhớ trong cả hai trường hợp (4 byte int
s so với 4 byte char
mảng), do đó, nó không thể là một vấn đề của đệm. Lý do gì có thể có cho việc sắp xếp lại này, và hơn nữa, có thể bằng cách nhìn vào mã C để xác định trước các biến cục bộ sẽ được sắp xếp không?
Bây giờ tôi biết rằng thông số ANSI cho C không nói gì về thứ tự các biến cục bộ được lưu trữ và trình biên dịch được phép chọn thứ tự riêng của nó, nhưng tôi sẽ tưởng tượng rằng trình biên dịch có quy tắc như thế nào nó sẽ chăm sóc điều này, và giải thích là tại sao những quy tắc đó lại được thực hiện như chúng.
Để tham khảo Tôi đang sử dụng GCC 4.0.1 trên Mac OS 10.5.7
có quan trọng không? bạn có cần các biến được phân bổ trong địa chỉ cụ thể không? – stefanB
Không, nó không quan trọng, chỉ là một bài tập học thuật. – David
Mức độ tối ưu hóa có ảnh hưởng đến câu trả lời không? Đoán thuần túy, nhưng có thể không có/tối ưu hóa thấp, ints là ứng cử viên cho phân bổ đăng ký nhưng char [4] thì không, và vì chúng được xử lý khác nhau, hai cơ chế chỉ xảy ra để đặt chúng trên stack theo các thứ tự khác nhau. Ngay cả khi tối ưu hóa không có sự khác biệt, nó là hợp lý rằng một cái gì đó khác trong cách tự động được xử lý có nghĩa là ints luôn luôn đi xuống một tuyến đường, và mảng luôn luôn xuống khác. –