Arduino sizeof Các đối tượng mảng Servo là .. sai?


7

Sau khi tìm kiếm khá lâu trên internet, tôi không còn cách nào khác ngoài việc thử hỏi ai đó xem họ có thể giải thích cho tôi tình huống có vẻ kỳ lạ này không.

Tôi đang thực hiện một số thử nghiệm bằng cách sử dụng một số động cơ servo, cố gắng di chuyển chúng gần như cùng nhau bằng cách sử dụng millis()Servođối tượng.

Tất nhiên, nó hoạt động hoặc cho các Servos đơn và nhiều servo.

Trường hợp, chi tiết hơn, là về điều này:

  1. Di chuyển một, hai hoặc nhiều động cơ servo cùng nhau.
  2. Buộc họ phải thực hiện cùng một lúc để hoàn thành bất kỳ hành động nào.
  3. Có số lượng động cơ servo.

Về hai điểm đầu tiên tôi không gặp vấn đề gì để giải quyết chúng, tôi dễ dàng tạo ra một chức năng và sau đó tạo một thư viện để hoàn thành công việc như vậy.

Tuy nhiên, vì tôi KHÔNG quen với C ++ và tôi đã tự hỏi liệu thực sự có thể tạo ra một mảng các đối tượng Servo, giống như bạn thực sự có thể làm, trên arduino, với các chuỗi:

String stringArray[] = {"string1", "string2", "and so on, I love it."};

Vì vậy, sau khi tự hỏi một lúc, tôi đã thử điều này:

Servo servObject;
Servo servObject_2;
Servo servObject_3;

Servo servos[] = {servObject, servObject_2, servObject_3};

Và bạn biết những gì mát mẻ? Hàm của tôi thực sự hoạt động chính xác bằng cách buộc số lượng phần tử của mảng servo.

Điều tôi muốn nói là điều đó là nếu tôi buộc chức năng của mình biết rằng nó sẽ có 3 phần tử vào mảng, tất nhiên, nó sẽ hoạt động; Tuy nhiên, vì một số lý do, nếu tôi sử dụng sizeof(servos);giá trị được trả về, thật đáng ngạc nhiên, là 2.... Hơn nữa, nếu tôi chỉ đẩy hai đối tượng servo thay vì ba vào mảng servo, nó sizeofsẽ trả về 6.

Bằng cách googling, tôi đã tìm ra một vài cuộc thảo luận về thực tế rằng, vì một số lý do, trong một số trường hợp, sizeof trả về một giá trị không chính xác (nếu tôi không sai thì đó là giá trị đúng -1), nhưng trong trường hợp của tôi nó dường như không theo bất kỳ logic nào cả.

Bảng tôi đang sử dụng là Arduino nano w / ATMEGA 328.

Bất kỳ ý tưởng về lý do tại sao nó không trả lại giá trị chính xác? Tôi thực sự sẽ hoàn toàn sai bởi vì tôi không nên tạo ra một loạt các đối tượng servo?

ps: Tôi đã không đăng toàn bộ mã bởi vì nó sẽ vô dụng, vì sizeof là hàm đầu tiên được gọi trong loop()

Trân trọng,

briosheje


Những gì bạn mô tả là kỳ lạ; bạn có thể vui lòng gửi mã chính xác để tính kích thước của mảng và hiển thị nó không (tôi cho rằng điều này là thông qua nối tiếp)?
jfpoilpret

@jfpoilpret: arduino hỗ trợ sizeofcấu trúc tiêu chuẩn có sẵn cho bất kỳ đối tượng mảng nào. Do đó, bất kỳ mảng nào (ví dụ: phần tử int [] = {2,3,1,3,9};) đều đưa ra giá trị chính xác của nó (trong trường hợp trước 5) và tôi nhận được giá trị trực tiếp từ cổng Nối tiếp. Trong mọi trường hợp, tối nay, tôi sẽ tải lên toàn bộ mã, tôi không ở nhà và thực sự không thể dán nó từ Nexus 5: P
briosheje

1
Sẽ rất hữu ích nếu bạn đăng một phiên bản mã của mình xuống mức tối thiểu cần thiết để chứng minh lợi nhuận sai.
JRobert

@JRobert: Tối nay tôi sẽ đăng toàn bộ mã, mặc dù, như tôi đã nói ở trên, mảng được khai báo (và điền) ngay trước khi thiết lập và ngay cả khi tôi in sizeofở đầu vòng lặp của mình, nó vẫn xuất ra như cũ giá trị như trong hàm mà tôi đang sử dụng nó. Ngoài ra, có cách nào khác để kiểm tra xem một phần tử mảng có tồn tại không? Nếu có thể, thì tôi có thể tự sizeoftạo nguyên mẫu.
briosheje

Quan điểm của tôi là việc ai đó dễ dàng thử một chương trình đơn giản hoặc tầm thường cho thấy lỗi đó là phải thử chương trình đầy đủ - có thể phụ thuộc vào phần cứng của bạn. Để trả lời câu hỏi của bạn, tôi sử dụng macro này #define countof(a) (sizeof(a)/sizeof(a[0]))để tìm # các phần tử trong một mảng, nhưng vì nó phụ thuộc vào sizeof()nó sẽ không giúp ích nhiều cho bạn.
JRobert

Câu trả lời:


7

Những gì bạn mô tả dường như là một vấn đề phổ biến mà nhiều nhà phát triển C hoặc C ++ có thể nhận được (hoặc có) sizeof.

Hãy xem đoạn mã sau:

char a[3];

int size(char b[]) {
    return sizeof b;
}

void setup() {
    int size1 = sizeof a;
    int size2 = size(a);
}

Trong mã đó, size1sẽ được đánh giá, bởi trình biên dịch, 3đó là kích thước thực của abiến, trong khi đó size2sẽ là 2.

Tại sao như vậy?

Điều này chỉ là do sizeof ađược trình biên dịch đánh giá và trình biên dịch biết rằng đó alà một mảng gồm 3 char; nhưng khi ađược truyền dưới dạng đối số cho hàm size(), nó được chuyển đổi thành một con trỏ (thành phần tử đầu tiên của mảng), do đó kích thước của nó là kích thước của một con trỏ , là 2byte trên AVR ATmega MCU.

Sự tinh tế này sizeofcó thể giải thích các giá trị lạ như bạn mô tả.

Làm thế nào để khắc phục vấn đề?

Hầu hết các hàm C lấy một mảng làm đối số sẽ yêu cầu một đối số khác cho biết kích thước của mảng; đó là cách (cách duy nhất tôi nghĩ) để giải quyết vấn đề này.

Đây là một mã mẫu:

Servo allServos[] = {...};
#define NUM_SERVOS (sizeof(allServos) / sizeof(Servo))
...
void handleServos(Servo *servos, int numServos) {
    for (int i = 0; i < numServos; i++) {
        servos[i].write(...);
        ...
    }
}

void loop() {
    handleServos(allServos, NUM_SERVOS);
}

Đó là thông lệ trong C để khai báo một mảng và ngay sau đó, xác định kích thước của nó như trên.


Ồ, cảm ơn, tôi không biết rằng sizeof, trong trường hợp đó, đã được giới thiệu đến con trỏ của Mảng. Vậy, có cách nào để có được kích thước thật của mảng đối tượng Servo ở trên không? Tôi có nên đếm từng yếu tố và sử dụng một bộ đếm?
briosheje

@briosheje xem bản chỉnh sửa mới nhất cho câu trả lời của tôi.
jfpoilpret

Cảm ơn! Nó hoạt động! :) Tôi đã xác nhận câu trả lời là giải pháp nhưng vẫn, cảm ơn vì lời giải thích rõ ràng!
briosheje
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.