2011-08-23 31 views
5

Tôi đang phát với thông số cuộc gọi của ngăn xếp và chức năng. Điều tôi muốn đạt được ở đây là lấy giá trị của các tham số biến trực tiếp bằng cách sử dụng ngăn xếp.Nhận đối số biến trực tiếp từ ngăn xếp

Nó hoạt động (hoặc có vẻ hoạt động) tốt khi tôi không sử dụng các thông số biến. Đây là những gì đang hoạt động:

void test(int a, int b) 
{ 
    unsigned char *ptr; 
    int i; 

    ptr = (unsigned char*)&a; 
    for (i = 0; i < 4; i++) 
    { 
     printf("%d,", *ptr); 
    }  
} 

Công việc đó, tôi có thể lấy giá trị của b; Cùng mã sử dụng

void test(int a, ...); 

làm nguyên mẫu của hàm không hoạt động.

Tôi không thể hiểu những gì đang xảy ra ở đây.

Bạn có thể giúp tôi? Cảm ơn!

Chỉnh sửa: Ok, sau đó có vẻ như không có cách nào ổn định và đáng tin cậy để tự mình làm những việc đó. Cho phép nói rằng trong hàm callee tôi biết kích thước dữ liệu (nhưng không phải kiểu) của đối số biến, có cách nào để lấy chúng không?

+4

Behavior Undefined gì bạn đang làm là. Bạn đang cố gắng đạt được điều gì? –

+1

Bạn đang cố gắng lấy các đối số biến như thế nào? Mẹo - stdargs.h, va_start, va_arg, va_end. – arunkumar

+0

@jweyric: Tôi đang sử dụng gcc. Tôi biết tôi có thể sử dụng va_ * macro, nhưng đó là hoàn toàn hết hạn, tôi chỉ đang cố gắng tìm hiểu cách hoạt động: P – Xaqq

Trả lời

1

Trong chức năng với ... bạn có thể sử dụng va_ * vĩ mô

void test(int a, ...) { 
    va_list ap; 
    va_start(ap, a); 
    // Your code 
    va_end(ap);  
} 
2

Chừng nào bạn biết hoặc có thể xác định số lượng đối số, bạn có thể sử dụng các macro từ <stdarg.h>:

#include <stdio.h> 
#include <stdarg.h> 

void test1(int n, ...) 
{ 
    va_list args; 
    va_start(args, n); 
    for (int i = 0; i < n; i++) 
    { 
     int j = va_arg(args, int); 
     printf("%d: %d\n", i, j); 
    } 
    va_end(args); 
} 

void test2(int a, ...) 
{ 
    va_list args; 
    int i = 0; 
    printf("%d: %d\n", i++, a); 
    va_start(args, a); 
    int j; 
    while ((j = va_arg(args, int)) > 0) 
     printf("%d: %d\n", i++, j); 
    va_end(args); 
} 

Sự khác biệt là làm thế nào hai chức năng này được gọi là:

int main(void) 
{ 
    test1(4, 1, 3, 7, 9); 
    test2(1, 3, 7, 9, 0); 
    return(0); 
} 

printf() gia đình sử dụng một kỹ thuật thay thế nhưng tương đương; những chức năng này quét chuỗi định dạng và xác định loại của mỗi đối số (cũng như số lượng đối số) từ thông tin trong chuỗi định dạng. Vì vậy, lựa chọn chính của bạn là:

  • đếm - test1()
  • sentinel - test2()
  • định dạng chuỗi - printf()
+0

Vấn đề với câu trả lời của bạn là bạn giả định rằng đối số là kiểu int.Trong trường hợp của tôi biết loại đối số của tôi không phải là một lựa chọn. Tôi biết các con số và kích thước của chúng. Làm cách nào tôi có thể coi chúng là dữ liệu nhị phân thô? Có cách nào để làm một cái gì đó như "data = va_arg (ap, get_size_from_somewhere()); Điều đó sẽ rất hữu ích bởi vì tôi sẽ có thể lưu trữ những dữ liệu như họ đang có. – Xaqq

+0

Ý tưởng: Tôi có thể xây dựng dữ liệu thô của tôi bằng cách sử dụng int, looping với va_arg() cho my_data_size/4 + 1 iterations.Nhưng sau đó, những gì về liên kết bộ nhớ hoặc đối số có kích thước 1 hoặc 2 byte? – Xaqq

+0

Nếu bạn không biết, hoặc không thể suy ra, loại biến trên Bạn không thể khai báo một biến cục bộ để giữ các tham số, tất cả đều khác nhau.Nếu bạn biết các loại, bạn có thể làm điều đó, tôi giả định một danh sách đồng nhất của các số nguyên vì nó là thuận tiện. nó, mã gọi phải cung cấp đầy đủ thông tin cho hàm được gọi là hàm được gọi biết số và kiểu (và gián tiếp kích thước) hoặc mỗi tham số được biểu diễn bằng dấu ba chấm (''...''). ý của bạn là 'dữ liệu nhị phân thô'; coi chúng là 'int' đồng nhất cái đó. –

Các vấn đề liên quan