2013-05-06 42 views
6

Tôi có một mảng các số nguyên không dấu cần lưu trữ con trỏ tới dữ liệu và chức năng cũng như một số dữ liệu. Trong thiết bị tôi đang làm việc với, con trỏ sizeof là giống như sizeof unsigned int. Làm thế nào tôi có thể cast con trỏ để chức năng vào int unsigned? Tôi biết rằng điều này làm cho mã không di động, nhưng nó là vi điều khiển cụ thể. Tôi cố gắng này:Con trỏ hàm chức năng đúc thành số nguyên trong C++

stackPtr[4] = reinterpret_cast<unsigned int>(task_ptr); 

nhưng nó cho tôi một lỗi "chuyển kiểu không hợp lệ"

Đúc nó để làm mất hiệu lực con trỏ và sau đó đến int được lộn xộn.

stackPtr[4] = reinterpret_cast<unsigned int>(static_cast<void *> (task_ptr)); 

Có cách nào làm sạch không?

Edit - task_ptr là chức năng con trỏ void task_ptr(void)

câu trả lời Tình yêu Barmar của, mất thiếu sót Portability của tôi đi. Ngoài ra mảng của con trỏ void thực sự có ý nghĩa hơn sau đó Unsigned Ints. Cảm ơn Barmar và isaach1000.

EDIT 2: OK, trình biên dịch của tôi đang nghĩ mô hình bộ nhớ lớn vì vậy nó đang sử dụng con trỏ 32 bit không 16 bit mà tôi đang mong đợi (nhỏ với tổng bộ nhớ 17K).

+1

Bạn không thể biến mảng thành mảng mảng con trỏ void? – isaach1000

+4

Làm thế nào về việc sử dụng một liên kết của con trỏ hàm và con trỏ dữ liệu? – Barmar

+1

Một 'reinterpret_cast' đơn giản sẽ hoạt động miễn là (a) kiểu số nguyên đủ lớn và (b) đó là con trỏ tới hàm bình thường (không phải thành viên hoặc thành viên tĩnh). Đó có phải là trường hợp ở đây không? Chính xác 'task_ptr' là gì? –

Trả lời

4

Một diễn viên kiểu C có thể vừa vặn với một hình bát giác vào lỗ hình thang, vì vậy tôi sẽ nói rằng với phần cứng và yêu cầu mục tiêu cực kỳ cụ thể của bạn, tôi sẽ sử dụng dàn diễn viên đó.

Cách khác, nhân đôi thành void* và sau đó int không có lợi thế làm cho mã nổi bật như ngón cái để người bảo quản trong tương lai biết điều gì đó đang diễn ra và có thể chú ý đặc biệt.

EDIT để nhận xét: Dường như trình biên dịch của bạn có thể có lỗi. Các mã sau biên dịch trên g ++ 4.5:

#include <iostream> 

int f() 
{ 
    return 0; 
} 

int main() 
{ 
    int value = (int)&f; 

    std::cout << value << std::endl; 
} 

EDIT2: Bạn cũng có thể muốn xem xét sử dụng các loại intptr_t thay vì int. Đó là một loại tích phân đủ lớn để giữ một con trỏ.

+0

Trình biên dịch C++ trả về lỗi khi tôi sử dụng kiểu đúc C: 'Lỗi [Pe171]: chuyển đổi loại không hợp lệ ' – user1135541

+1

+1 cho' intptr_t' – Oktalist

+1

Thật không may, 'intptr_t' không được chỉ định để cho phép chức năng chuyển đổi con trỏ chuyển đổi Vì vậy, không có cách rõ ràng để đảm bảo rằng mã của bạn sẽ không biên dịch trên các hệ thống mà các con trỏ hàm sẽ không khớp với 'intptr_t'. – SamB

-1

Đây là ansi compliant:

int MyFunc(void* p) 
{ 
    return 1; 
} 

int main() 
{ 
    int arr[2]; 
    int (*foo)(int*); 

    arr[0] = (int)(MyFunc); 

    foo = (int (*)(int*))(arr[0]); 

    arr[1] = (*foo)(NULL); 
} 
+0

Cố gắng điều đó, nhưng C++ của tôi than phiền, 'loại chuyển đổi không hợp lệ'. Cần một cách C++ chuẩn để thực hiện nó – user1135541

+0

Điều này cũng được biên dịch trong C + +, chính xác lỗi nào bạn nhận được là – lsalamon

+3

Lần cuối cùng tôi kiểm tra,' void main() ' –

2

Trong C++ một con trỏ có thể được chuyển đổi sang một giá trị của một loại không thể thiếu đủ lớn để giữ nó. Loại được hỗ trợ có điều kiện std::intptr_t được xác định sao cho bạn có thể chuyển đổi void* thành intptr_t và quay lại để nhận giá trị ban đầu. Nếu void* có kích thước bằng hoặc lớn hơn con trỏ hàm trên nền tảng của bạn thì bạn có thể thực hiện chuyển đổi theo cách sau.

#include <cstdint> 
#include <cassert> 

void foo() {} 

int main() { 
    void (*a)() = &foo; 

    std::intptr_t b = reinterpret_cast<std::intptr_t>(a); 

    void (*c)() = reinterpret_cast<void(*)()>(b); 
    assert(a==c); 
} 
+0

Nó cũng được điều kiện có hỗ trợ hay không 'a' có thể được diễn giải lại thành' b', ngay cả khi 'intptr_t' tồn tại. (Tuy nhiên nó được đảm bảo rằng nếu hỗ trợ như vậy tồn tại, sau đó 'a == c'). –

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