2010-04-30 29 views
7

Tôi có biến dài 32 bit, CurrentPosition, mà tôi muốn chia thành 4, 8 ký tự. Làm thế nào tôi sẽ làm điều đó hiệu quả nhất trong C? Tôi đang làm việc với một MCU 8bit, kiến ​​trúc 8051.Làm thế nào để phân chia một giá trị dài (32 bit) thành bốn biến char (8bits) bằng cách sử dụng C?

unsigned long CurrentPosition = 7654321; 
unsigned char CP1 = 0; 
unsigned char CP2 = 0; 
unsigned char CP3 = 0; 
unsigned char CP4 = 0; 
// What do I do next? 

Tôi có nên chỉ tham chiếu địa chỉ bắt đầu của CurrentPosition bằng con trỏ và sau đó thêm 8 hai địa chỉ đó bốn lần?

Đó là chút Endian.

CSONG tôi muốn CurrentPosition không thay đổi.

+2

Người cuối cùng nào? ___ – kennytm

+0

Tôi đang sử dụng SDCC với việc sử dụng định dạng Little Endian – PICyourBrain

Trả lời

13
CP1 = (CurrentPosition & 0xff000000UL) >> 24; 
    CP2 = (CurrentPosition & 0x00ff0000UL) >> 16; 
    CP3 = (CurrentPosition & 0x0000ff00UL) >> 8; 
    CP4 = (CurrentPosition & 0x000000ffUL)  ; 

Bạn có thể truy cập vào các byte thông qua một con trỏ là tốt,

unsigned char *p = (unsigned char*)&CurrentPosition; 
//use p[0],p[1],p[2],p[3] to access the bytes. 
+0

1) Tôi có cần phải đúc chúng với (unsigned char) không? 2) Điều này có khiến cho CurrentPosition không bị ảnh hưởng không? – PICyourBrain

+1

1. Trước đây cần đúc 2. Cả hai phương thức đều để CurrentPosition không bị ảnh hưởng – Saul

+0

Trước đây không cần * đúc, nhưng một số trình biên dịch sẽ đưa ra cảnh báo không chính xác về khả năng mất chính xác nếu bạn không. – caf

0
CP1 = (unsigned char)(CurrentPosition & 0xFF); 
CurrentPosition >>= 8; 
CP2 = (unsigned char)(CurrentPosition & 0xFF); 
... 
+0

Điều này sẽ thay đổi giá trị trong CurrentPosition phải không? Tôi muốn giữ nguyên CurrentPosition. – PICyourBrain

+0

Có, một tùy chọn là tạo một bản sao của CurrentPosition và mangle bản sao. Hoặc câu trả lời của nos là một lựa chọn khác. Ý tưởng của bạn về việc sử dụng một con trỏ cũng có thể.Có nhiều cách để làm điều này. –

2

Nếu bạn đang sử dụng một MCU 8 bit chuyển một biến toàn bộ 32 bit là một chút công việc. Trong trường hợp này tốt hơn nên đọc 4 byte của CurrentPosition bằng cách sử dụng số học con trỏ. Diễn viên:

unsigned char *p = (unsigned char*)&CurrentPosition; 

không thay đổi CurrentPosition, nhưng nếu bạn cố gắng viết thư cho p [0] Bạn sẽ thay đổi byte ít quan trọng nhất của CurrentPosition. Nếu bạn muốn một bản sao làm điều này:

unsigned char *p = (unsigned char*)&CurrentPosition; 
unsigned char arr[4]; 
arr[0] = p[0]; 
arr[1] = p[1]; 
arr[2] = p[2]; 
arr[3] = p[3]; 

và làm việc với arr. (Nếu bạn muốn byte quan trọng nhất đầu tiên thay đổi thứ tự trong các bài tập đó).

Nếu bạn thích 4 biến Bạn rõ ràng có thể làm:

unsigned char CP1 = p[0]; 
unsigned char CP2 = p[1]; 
unsigned char CP3 = p[2]; 
unsigned char CP4 = p[3]; 
+0

Giải pháp này tốt hơn nếu bạn không thể chuyển trực tiếp int 32 bit. –

5

Tôi nghĩ bạn nên xem xét sử dụng một sự kết hợp:

union { 
    unsigned long position; 
    unsigned char bytes[4]; 
} CurrentPosition; 

CurrentPosition.position = 7654321; 

Các byte bây giờ có thể được truy cập như: CurrentPosition.bytes [0 ], ..., CurrentPosition.bytes [3]

+0

Một ý tưởng tốt trong thực tế vì trình biên dịch có thể thực hiện phân tách của int thành byte. Một ý tưởng tồi trong lý thuyết vì việc sử dụng các công đoàn này không được xác định bởi tiêu chuẩn c .. (hầu hết nếu không phải tất cả các triển khai sẽ hoạt động) –

+0

@Nils Kiểu xảo quyệt với các công đoàn đã được xác định rõ ràng từ C99. Mã vẫn là người phụ thuộc cuối cùng. – user694733

0
unsigned char *CP = &CurrentPosition; 

Bây giờ CPn trên mã ban đầu của bạn được truy cập qua CP[n].

0

Tôi biết điều này đã được đăng một số thời gian trước đây. Nhưng đối với bất cứ ai vẫn đọc chủ đề: Nhiều người có cách tiếp cận tuần tự chuyển giá trị ban đầu. Tại sao không để trình biên dịch thực hiện công việc cho bạn. Sử dụng công đoàn & để cho phép bạn lưu trữ các giá trị trong cùng một vị trí. Xác định một liên minh bao gồm cả biến dài 32 bit (đây sẽ là nơi bạn lưu CurrentPosition) và một cấu trúc gồm 4 biến char. Hoặc chỉ là một mảng số nguyên 8 bit đơn giản. Khi bạn viết CurrentPosition của bạn vào biến dài, nó sẽ được lưu trữ trong cùng một vị trí được truy cập khi bạn đọc 4 biến char. Phương pháp này ít tốn nhiều công sức hơn và không cho phép trình biên dịch thực hiện công việc thay vì lãng phí thời gian & tài nguyên.

+1

Đó là chính xác những gì [thứ hai trả lời upvoted nhất] (https://stackoverflow.com/a/2747324/2564301) cho thấy. – usr2564301

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