Это не массив. А если написать Код (C++): unsigned char massiv[] = SSD1306_INITIALIZATION_DATA_ARRAY; То и sizeof отлично работает.
sizeof -- очень простой оператор, он вычисляет размер данных в байтах. Он не вычисляет количество элементов в массиве, он вычисляет размер этого массива в байтах, не зависимо от размера элементов массива. Размер массива в байтах не будет соответствовать количеству элементов массива, если размер элементов массива больше одного байта. И нет тут ни какой "мути" -- всё просто и прозрачно до безобразия.
Учитывая обстоятельства, что в макросе, который определяет содержимое массива, используются другие макросы, которые могут быть определены как '0', этот "костыль" превращается в головную боль.
Это не костыль, а решение, которое позволяет передавать в интерфейс определённое количество байт. Сколько байт передавать, определяется первым байтом в строчке. Далее двигаем "каретку" на один элемент вперёд и рисуем байты в интерфейс. Затем переходим на следующую строчку, считываем количество байт и так далее. Такая замута потребовалась для трансиверов от SiLabs. За раз в него можно напихать не более 15 мать их чтоле байт. А всего вместе с патчем необходимо передать что-то около 800 байт для его конфигурации. В SSD1306 такое не требуется, поэтому переделал на обычное написание: Код (C++): #define SSD1306_INITIALIZATION_DATA_ARRAY { \ SSD1306_CMD_SET_DISPLAY_OFF, \ SSD1306_SET_MULTIPLEX_RATIO, \ SSD1306_SET_DISPLAY_OFFSET, \ SSD1306_SET_DISPLAY_START_LINE, \ SSD1306_SET_SEGMENT_REMAP_SEG0, \ SSD1306_SET_OUTPUT_SCAN_DIRECTION, \ SSD1306_SET_ADDRESSING_MODE, \ SSD1306_SET_PINS_HARDWARE_CONF, \ SSD1306_SET_CONTRAST_CONTROL, \ SSD1306_ENTIRE_DISPLAY_ON, \ SSD1306_SET_NORMAL_INVERSE_DISPLAY, \ SSD1306_SET_DISPLAY_CLOCK, \ SSD1306_SET_PRECHARGE_PERIOD, \ SSD1306_SET_VCOMH_DESELECT_LEVEL, \ SSD1306_CMD_DEACTIVATE_SCROLL, \ SSD1306_CHARGE_PUMP_SETTING, \ SSD1306_CMD_SET_DISPLAY_ON, \ } Ну и как тут подсказали, sizeof() на это...
Застрял на такой задачке. Есть такая структура: Код (C++): typedef struct { const unsigned char *data; uint8_t width; uint8_t height; uint8_t dataSize; } tImage; Данные примерно в таком виде: Код (C++): static const uint8_t image_data_Font_0xfe[18] = { 0x00, 0xc0, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x80, 0x00, 0x07, 0x02, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01 }; static const tImage Font_0xfe = { image_data_Font_0xfe, 9, 16, 8}; static const uint8_t image_data_Font_0xff[14] = { 0x00, 0x80, 0x40, 0x40, 0x80, 0x00, 0xc0, 0x04, 0x05, 0x02, 0x02, 0x01, 0x01, 0x07 }; static const tImage Font_0xff = { image_data_Font_0xff, 7, 16, 8}; Через указатели получаю адрес требуемой структуры во флеше: Код (C++): uint8_t char_width; const tImage* image_font; uint8_t* data; image_font = Get_Char_Data(c); if (image_font) { char_width = image_font->width; data = (uint8_t*)image_font->data; /* ...... */ } Все данные получаю валидные по адресам из флеша (смотрю дебагом), а вот Код (C++): sizeof(image_font->data) возвращет чепуху (2 байта, но должно вернуться 14, 18 ...). Как натравить этот мутный оператор (с) на массив через поле структуры?
Ну и где тут чепуха? Сел за руль машины, включил заднюю, нажал не газ, и начинаешь возмущаться -- "а чой-то она назад поехала, а не вперёд как я хочу!?!?!" sizeof вычисляет размер данных, хранимых в переменной на основе типа этой переменной. Какой тип у переменной 'image_font->data'? Правильно -- const unsigned char *data -- это указатель. Какой размер данных у переменной типа "указатель"? Зависит от архитектуры, в твоём случае 2 байта. В том-то и беда, что натравливаешь это простейший оператор не на массив, а на указатель, который указывает на ячейку памяти типа 'unsigned char' размером 1 (один) байт. Если хочешь узнать размер данных, на которые указывает указатель, то сначала твоя программа должна узнать "а на данные какого типа указывает указатель?". Узнав этот тип, передаёшь его оператору 'sizeof' и получаешь нужный тебе ответ. PS: тебе надо разобраться -- что такое указатели и с чем их едят....
Я не знаю никакого способа приведения указателя к массиву. Получается, размер массива надо передавать отдельно.
Это потому, что в языке 'C' нет способа сделать указатель на массив -- такой тип как массив есть, а указателя на него нет (наверное единственный тип, для которого в этом языке нельзя сделать указатель).
в языке Си нет такого типа как "массив" - поэтому и указателя нет. Вместо массива в Си есть область памяти. заполненная переменными данного типа. И есть указатель на начало этой области. Вполне логично. что этот указатель имеет тип элемента. а не массива.
не обязательно отдельно. Можешь хранить размер структуры в первом элементе. Или ставить в конце массива терминатор, как в классических С-type строках Но в любом случае в твоей структуре за размером массива должен следить ты сам, компилятор тут не справится
Разработчики языка 'C' с Вами не согласны. Вот выдержка из стандарта 'ANSI C' (ISO/IEC 9899): В разделе описываются производные типы, такие как -- массив, структура, объединение и т.д. UPD: Исходя из текста стандарта и Вашего заявления, можно продолжить мысль, что и структура тоже на является типом, и на неё не может быть указателя.
В классических строках не встречается "\0", за исключением как только конец строки. В массиве данных 0 может встречаться как элемент массива. Почему не передать размер массива как отдельный параметр? Вот зачем эти костыли? Как по мне в Си все очень однозначно и понятно. Можно же так: Код (C++): typedef struct { const unsigned char *data; uint8_t data_size; uint8_t width; uint8_t height; uint8_t dataSize; } tImage; static const uint8_t image_data_Font_0xfe[] = { 0x00, 0xc0, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x80, 0x00, 0x07, 0x02, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01 }; static const tImage Font_0xfe = { image_data_Font_0xfe, sizeof(image_data_Font_0xfe), \\ 9, 16, 8}; static const uint8_t image_data_Font_0xff[] = { 0x00, 0x80, 0x40, 0x40, 0x80, 0x00, 0xc0, 0x04, 0x05, 0x02, 0x02, 0x01, 0x01, 0x07 }; static const tImage Font_0xff = { image_data_Font_0xff,sizeof(image_data_Font_0xff), \\ 7, 16, 8};