Что означает &buffer[i*4]???

junior_developer
Offline
Зарегистрирован: 27.11.2017

Помогите пожалуйста разобраться, что означает &buffer[i*4]???
Вот функция целиком
 

for (int i=0; i < 4; i++) {
    //data is writen in blocks of 4 bytes (4 bytes per page)
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer[i*4], 4);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Read() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }
  }

та же функция...

StatusCode 	MIFARE_Ultralight_Write (byte page, byte *buffer, byte bufferSize)

Её тип StatusCode? То есть при return она возвращает код определенной команды?

С первым параметром всё понятно. Адрес страницы увеличивается в цикле за счет i++. Верно?
Третий параметр это размер буфера в байтах? Или нет?
А вот что означает второй параметр - для меня "темный лес"? Зачем там значок "&"? Это указатель на адрес памяти? И самое непонятное почему там стоит [i*4]? Это умножение значения переменной i на 4? 
Не могу понять, зачем её умножать? 

Объясните пожалуйста новичку! Заранее спасибо!
Привожу код примера целиком:

/* mifare ultralight example (25-02-2018)
 * 
 *   RFID-RC522 (SPI connexion)
 *   
 *   CARD RC522      Arduino (UNO)
 *     SDA  -----------  10 (Configurable, see SS_PIN constant)
 *     SCK  -----------  13
 *     MOSI -----------  11
 *     MISO -----------  12
 *     IRQ  -----------  
 *     GND  -----------  GND
 *     RST  -----------  9 (onfigurable, see RST_PIN constant)
 *     3.3V ----------- 3.3V
 *     
 */

  #include <SPI.h>
  #include <MFRC522.h>
  
  
  #define SS_PIN          10
  #define RST_PIN         9

  MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
  MFRC522::StatusCode status; //variable to get card status
  
  byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);

  uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                            //Ultraligth mem = 16 pages. 4 bytes per page.  
                            //Pages 0 to 4 are for special functions.           
  
void setup() {
  Serial.begin(9600); // Initialize serial communications with the PC
  SPI.begin(); // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card  
  Serial.println(F("Sketch has been started!"));
  memcpy(buffer,"HELLO WORLD! ;-)",16);
}

void loop() {
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
    return;

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
    return;

  // Write data ***********************************************
  for (int i=0; i < 4; i++) {
    //data is writen in blocks of 4 bytes (4 bytes per page)
    status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer[i*4], 4);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Read() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
    }
  }
  Serial.println(F("MIFARE_Ultralight_Write() OK "));
  Serial.println();


  // Read data ***************************************************
  Serial.println(F("Reading data ... "));
  //data in 4 block is readed at once.
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  Serial.print(F("Readed data: "));
  //Dump a byte array to Serial
  for (byte i = 0; i < 16; i++) {
    Serial.write(buffer[i]);
  }
  Serial.println();

  mfrc522.PICC_HaltA();

}

Нашел его здесь

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

junior_developer пишет:

что означает &buffer[i*4]???

Адрес i-того 4-х байтового блока в массиве buffer.

junior_developer
Offline
Зарегистрирован: 27.11.2017
Большое спасибо за помощь!
 
Значок "&" означает вернуть адрес. Если бы было
p = &buffer;
то это значит, что в переменную p записывается адрес переменной buffer. Правильно?
Однако здесь не просто переменная, а массив. И насколько я понял, обращение идет по его индексу.
то есть, если написать так p = &buffer[i];
то это значит, поместить в переменную p адрес элемента массива с индексом i. Правильно?
Индекс нассива начинается с 0 (нуля). И если начать его множить на 4 (четыре). Как там написано [i*4], то получится
0*4=0;
1*4=4;
2*4=8;
3*4=12;
в буфер попадут адреса элементов массива с индексами 0, 4, 8, 12? Я правильно понял?
 
А можно ещё вопрос про эти две строчки:
byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);

 

 Первая значит, что создается массив из 18-ти байтов? Насчет sizeof понятно, что в переменную size попадает размер. Только непонятно, почему там 18 байтов, а не 16? Два байта контрольная сумма? Она как-то добавляется автоматически в зависимости от размера (количества байтов)?
 
Если записывать не 16, а 32 байта, то размер буфера должен быть просто в два раза больше?  
sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, наверное, пейсатель скретча создаст функцию вычисления uint16_t crc16=getCRC(buffer, sizeof(buffer)-sizeof(uint16_t)) и поместит его в последние два байта - *((uint16_t*) &buffer[sizeof(buffer)-sizeof(uint16_t)]) = crc16;

Конечно это потом будет "автоматически".

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

sadman41 пишет:

 *((uint16_t*) &buffer[sizeof(buffer)-sizeof(uint16_t)]) = crc16;

Если это медленно и распевно произнести вслух, то можно вызвать демона... ну не самого главного, но все же... ;)))

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Я бы себя убил за такую запись.

sadman41
Offline
Зарегистрирован: 19.10.2016

Запишите проще и чтобы там были все элементы, которые пытается разучить джуниор. Впитаю ваш опыт, так скыть.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Нет уж, ваш способ универсальный и переносимый, спору нет. Но он неудобочитаемый. Однако, когда пишешь для конкретного железа, можно просто: buffer[sizeof(buffer)-2] = LOWBYTE(crc16); buffer[sizeof(buffer)-1] = HIGHBYTE(crc16); или какой там у вас big-little-endian. Или ещё сто способов, без вложенных разыменований. Причём для 8-битного контроллера - это нативнее.

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, за нативность я не буду говорить - надо посмотреть, конечно, что там в ассемблер прилетит. Мошт с lowByte() / highByte() то на то и выйдет. Плюс еще с эндианами разбирайся... За нечитаемость не спорю. Но, раз уж человек хотел поупражняться с адресацией, то я ему для закрепления написал пример.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Эти макросы компилятор обычно превращает просто в младший или старший байт, ну или в их адрес, если адресация памяти не прямая. Думаю, в моём примере будет две или три ассемблерных инструкции. Было бы интересно вашу запись посмотреть, подозреваю что то же самое получиться, gcc умный. Вроде где-то натыкался как сказать IDE, чтобы асм сразу делала?

junior_developer
Offline
Зарегистрирован: 27.11.2017

sadman41 пишет:

Ну, наверное, пейсатель скретча создаст функцию вычисления uint16_t crc16=getCRC(buffer, sizeof(buffer)-sizeof(uint16_t)) и поместит его в последние два байта - *((uint16_t*) &buffer[sizeof(buffer)-sizeof(uint16_t)]) = crc16;

Конечно это потом будет "автоматически".

Помогите пожалуйста перевести это на человеческий язык, а то мне кажется, что сам не осилю :)
Для начала строчка

uint16_t crc16=getCRC(buffer, sizeof(buffer)-sizeof(uint16_t))

Это создание шестнадцати-битной переменной, с названием crt16. Правильно?
В эту переменную заносится выражение справа.  В нём функция getCRC, которая есть в стандартной библиотеке С++?  Она высчитывает контрольную сумму из того, что в скобках.
sizeof(buffer)  размер переменной buffer в байтах
sizeof(uint16_t) размер типа данных uint16_t   16 бит или 2 байта. Правильно?
(sizeof(buffer) - sizeof(uint16_t)) означает вычитание из размера буфера 16 бит или 2 байт?

А как расшифровать это

*((uint16_t*) &buffer[sizeof(buffer)-sizeof(uint16_t)]) = crc16;

 Значок * обозначает создание указателя? Чтобы понять, куда он указывает, нужно посчитать, что в скобках?
Скобок тут куча, и я даже не совсем понимаю, в какой последовательности это обрабатывается компилятором!
Что означает (uint16_t*)? Зачем там звездочка?

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

"Козюльский! Перестаньте сказать!" (с)

Конечно, вариант Садмана1 гораздо читаемее и легче понимаем, что та околесица, которую написал Шварц78.

Для микроконтроллеров НЕ ПИШУТ переносимый код. Вот потому, что это нахер никому не нужно - переносить некуда, весь код контроллера насквозь аппаратно-зависим от конкретного контроллера. Поэтому и union и адресная арифметика с конкретным порядком байт - НОРМА для контроллеров.

Уже тут на фолруме, только на моей памяти, раза три копья ломали. Итог - не нужно тащить в эмбеддинг всю херату из большого програмирования для компьютеров.

-----

дополню: и не надо стесняться писать просто 2, вместо sizeof(uint16_t) ! ;))) Вот это выглядело глупо.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Такие выражения надо справа налево читать. buffer[sizeof(buffer)-sizeof(uint16_t) - это элемент в массиве, где дожна лежать контр. сумма. & - это взятие адреса сего элемента. (uint16_t*) - это для компилятора, приведение типа этого адреса к указателю на тип uint16_t. Ну и * - разыменование, то есть значение по адресу указателя. Теперь мы имеем указатель на uin16_t, по адресу которого присваиваем значение crc16/

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Уважаемый, поясните за околесицу. Я вообще-то только для контроллеров и программировал(почти), и про непереносимость кода могу много рассказать. Так как Садаман никто для контроллеров не пишет. А вот почему у меня околесица? Я начинал с ассемблера, и примерно понимаю какой код даёт компилятор для 8-биток, а вы?

И ещё у вас взаимоисключающие параграфы, извините уж, что оцениваю ваше психофизическое состояние))

sadman41
Offline
Зарегистрирован: 19.10.2016

junior_developer пишет:

А как расшифровать это

*((uint16_t*) &buffer[sizeof(buffer)-sizeof(uint16_t)]) = crc16;

 Значок * обозначает создание указателя? Чтобы понять, куда он указывает, нужно посчитать, что в скобках?
Скобок тут куча, и я даже не совсем понимаю, в какой последовательности это обрабатывается компилятором!
Что означает (uint16_t*)? Зачем там звездочка?

buffer[sizeof(buffer)-sizeof(uint16_t)] - "взяли" какой-то элемент в байтовом (это важно) массиве.
 
&buffer[...] - получили его адрес в RAM. Массив же не просто так валяется, а адресуемо. Так же адресуем и какой-либо его элемент.
 
(uint16_t*) - говорим компилятору, чтобы он временно два байта, начиная с заданного адреса (см. выше), рассматривал как адрес переменной типа uint16_t. Имени у этой переменной нет, есть просто адрес.
 
*(...) = crc16 - теперь в эти два байта (по адресу) копируем ранее вычисленный CRC . Так, как он тоже uint16_t, то всё влезает ровненько в последние 2 байта массива buffer. 
 
Теперь в буфере и данные и CRC - можно передавать всю кучу куда-нить через .write(buffer, sizeof(buffer)).

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Schwarz78 пишет:

Эти макросы компилятор обычно превращает просто в младший или старший байт, ну или в их адрес, если адресация памяти не прямая. Думаю, в моём примере будет две или три ассемблерных инструкции. Было бы интересно вашу запись посмотреть, подозреваю что то же самое получиться, gcc умный. Вроде где-то натыкался как сказать IDE, чтобы асм сразу делала?

Да я бы вообще это сделал через ((struct*) )->... если честно. Мне так понятней даже.  

А IDE ASM не отдает. Надо как-то там попрыгать с командной строкой, чтобы из объектника дизассемблировать. 

https://godbolt.org/z/LleiJi

Насколько я понимаю, вот этот кусок:

        mov r24,r28
        mov r25,r29
        adiw r24,17
        ldd r18,Y+19
        ldd r19,Y+20
        mov r30,r24
        mov r31,r25
        std Z+1,r19
        st Z,r18

 

А вот вариант с lowByte/highByte: https://godbolt.org/z/y0TKa8

 

        ldd r24,Y+19
        ldd r25,Y+20
        std Y+17,r24
        ldd r24,Y+19
        ldd r25,Y+20
        mov r24,r25
        clr r25
        std Y+18,r24

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Schwarz78 пишет:

Уважаемый, поясните за околесицу.

lowByte() и highByte()

Это не удобство, а чушь собачья. Недаром в самой avr-libc это глупости нету.

Корни этой премудрости растут в извращенном желании ардуино-сообщества "впрясть в телегу вола и трепетную лань". То есть построить единую экосистему и для АВР и для АРМ и ЕСП8266 и ещё  хрен-знает-чего.

Получилось то, что получилось - замечательная вещь для популяризации идеи МК. Но, как только человек изучает программирование достаточно (например узанет, зачем нужны ссылки ;))))) -без обид!), он перестает пользоваться большей частью этой экосистемы.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Именно так. Но, поскольку массив и crc16, то где-то здесь явно последовательная передача(serial), и самое время подумать, в каком порядке читает uint16_t принимающая машина (little endian или big).

Schwarz78
Offline
Зарегистрирован: 19.01.2019

wdrakula пишет:

lowByte() и highByte()

Это не удобство, а чушь собачья. Недаром в самой avr-libc это глупости нету.

Во всех 8-битных контроллерах и компиляторах для них эти макросы так или иначе определены, и очень прозрачно превращаются именно в старший или младший байт. Для 16-битного int, конечно. Для меня это как данность уже. С MSP430 или ARM32 буде конечно не так, но здесь у нас AVR в основном. Ну и посмотрите как это выглядит в Arduino.h:

#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))

Вполне предсказуемо.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

sadman41 пишет:

А IDE ASM не отдает. Надо как-то там попрыгать с командной строкой, чтобы из объектника дизассемблировать. 

Не нужно ходить на тот сайт, компиляция сильно зависит от настроек линковщика и оптимизатора.

/ПУТЬ-К-ИДЕ/hardware/tools/avr/bin/avr-objdump -S ИМЯ-СКЕТЧА.ino.elf >> Куда-тебе-надо.S

 Запустить в том каталоге, куда ИДЕ складывает все после компиляции

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Schwarz78 пишет:

wdrakula пишет:

lowByte() и highByte()

Это не удобство, а чушь собачья. Недаром в самой avr-libc это глупости нету.

Во всех 8-битных контроллерах и компиляторах для них эти макросы так или иначе определены, и очень прозрачно превращаются именно в старший или младший байт. Для 16-битного int, конечно. Для меня это как данность уже. С MSP430 или ARM32 буде конечно не так, но здесь у нас AVR в основном. Ну и посмотрите как это выглядит в Arduino.h:

#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))

Вполне предсказуемо.

;))) А ты забавный! Спасибо, дорогой, я уже их видел... краем глаза. ;))))

Я не о том, как они определены. А о том, что их использовать не стоит. Хотя это личное дело каждого.

Например: ты насколько знаешь команды АВР? Это не подколка, не принимай на свой счет. Просто сдвиг на 8 в авр БЕЗ оптимизации - это ровно 8 сдвигов. ;)))

Schwarz78
Offline
Зарегистрирован: 19.01.2019

wdrakula пишет:

Не нужно ходить на тот сайт, компиляция сильно зависит от настроек линковщика и оптимизатора.

Я бы сказал - от оптимизатора, линковщик только линкует.

wdrakula пишет:

/ПУТЬ-К-ИДЕ/hardware/tools/avr/bin/avr-objdump -S ИМЯ-СКЕТЧА.ino.elf >> Куда-тебе-надо.S

 Запустить в том каталоге, куда ИДЕ складывает все после компиляции

О, за это спасибо, я когда-то ходил этим путём, но уже забыл, а гуглить лень на ночь глядя.

sadman41
Offline
Зарегистрирован: 19.10.2016

wdrakula пишет:

Не нужно ходить на тот сайт, компиляция сильно зависит от настроек линковщика и оптимизатора.

Да я в научные изыскания не хочу погружаться. Так, прикинуть быстро что почём.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Думаю не открою тебе секрета, если скажу, что препроцессор не станет ничего сдвигать, а компилятор тем более не идиот. Он просто подставит старший или младший байт.

И потом, как писать - личное дело каждого. Я тоже люблю объединения, они однозначнее. И ваще - препроцессор зло. Хотя есть такие штуки, которые очень вкусные с препроцессором.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Schwarz78 пишет:

wdrakula пишет:

Не нужно ходить на тот сайт, компиляция сильно зависит от настроек линковщика и оптимизатора.

Я бы сказал - от оптимизатора, линковщик только линкует.

Пожалуйста, не нужно спорить... по крайней мере, пока со ссылками не разберешся ;))).

-flto - опция линковщика. Ты не поверишь, но так и называццо: link time optimization ;))))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Schwarz78 пишет:

Думаю не открою тебе секрета, если скажу, что препроцессор не станет ничего сдвигать, а компилятор тем более не идиот. Он просто подставит старший или младший байт.

Ты не научился читать? Я написал - БЕЗ оптимизации. Так без нее компилятор ничего не уберет из авторского кода, не сократит и не заменит.

В командах АВР нет сдвига с параметром, только на 1 бит.

Никогда, на этом форуме, не нужно со мной спорить.... ну пожалуйста-пожалуйста-пожалуйста!!!! ;)))

Если я берусь о чем-то рассказывать, то это из области педагогики. Просто о том, "из чего, на самом деле, тетька сделана". Все для народа стараюсь... руки в кровь стёр! ;)))

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Ну, предположим что lto работает и для avr. Доволен? Я не спорю.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

wdrakula пишет:

Ты не научился читать? Я написал - БЕЗ оптимизации. Так без нее компилятор ничего не уберет из авторского кода, не сократит и не заменит.

В командах АВР нет сдвига с параметром, только на 1 бит.

Никогда, на этом форуме, не нужно со мной спорить.... ну пожалуйста-пожалуйста-пожалуйста!!!! ;)))

Да, эту ремарочку я заметил, и подумал что за неё ты и уцепишься, когда я отвечу. Ну что тебе сказать про Сахалин... ))

Про машинные команды мне не рассказывай, уважь и ты меня.

Как я и написал выше, не спорю, мне просто даже любопытно)

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ОК, я - спать, а то мне еще 40 минут под кислородом лежать, а в Мск уже почти полночь... старый я и больной... да и самогонка кончилась ;). Удачи.

----

ЗЫ: Про ссылки - Женя не стал тебя в той теме сильно грузить, но при использовании лямбда-функций без них очень будет трудно.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Я тоже спать, а про ссылки я ещё почитал, и немножко осознал чем они лучше указателей. Буду дальше учиться) Мне бшаблоны ещё понять, куда мне до лямбды. Очень я современное языкознание запустил. Спокойной.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

wdrakula пишет:

Ты не научился читать? Я написал - БЕЗ оптимизации. Так без нее компилятор ничего не уберет из авторского кода, не сократит и не заменит.

В командах АВР нет сдвига с параметром, только на 1 бит.

wdrakula, там сдвигом препроцессор заведует, который подставит компилятору уже вычисленные значения. Оптимизация туть ни при чём.   

 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

DetSimen пишет:

 сдвигом препроцессор заведует, который подставит компилятору уже вычисленные значения. Оптимизация туть ни при чём.   

Не-не-не. Препроцессор только подставами занимается. Известно ведь, если написать #define x 1+1, а потом x = x * 10; - получим 11, а не 20.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Schwarz78 пишет:

DetSimen пишет:

 сдвигом препроцессор заведует, который подставит компилятору уже вычисленные значения. Оптимизация туть ни при чём.   

Не-не-не. Препроцессор только подставами занимается. Известно ведь, если написать #define x 1+1, а потом x = x * 10; - получим 11, а не 20.

Я тут утром, в мрачном расположении духа, поглядел на варианты компиляции сдвигов с разными

#pragma GCC optimize ("-опция") //всё интересное при -o0 -конечно!

..... не стану рассказывать. Это любопытно для эрудиции. x<<8 нет, не 8 сдвигов, все-таки! Но x<<3 сильно удивит!

Это ни в коем случае не претензия к GCC! Скорее просто любопытно и весело.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

DetSimen пишет:

wdrakula пишет:

Ты не научился читать? Я написал - БЕЗ оптимизации. Так без нее компилятор ничего не уберет из авторского кода, не сократит и не заменит.

В командах АВР нет сдвига с параметром, только на 1 бит.

wdrakula, там сдвигом препроцессор заведует, который подставит компилятору уже вычисленные значения. Оптимизация туть ни при чём.   

 

Ну да.  Это я сдура ляпнул. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Так что в итоге - экономней пользоваться вызовом демона, struct или highByte() ?

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Помучался я немного с оптимизатором пока удалось честно скомпилировать. В общем - одинаковый код, как я и думал. Вот ваш:

  *(volatile uint16_t*) &buffer[sizeof(buffer) - sizeof(uint16_t)] = crc16;
 214:	84 ee       	ldi	r24, 0xE4	; 228
 216:	9a ef       	ldi	r25, 0xFA	; 250
 218:	9a 8b       	std	Y+18, r25	; 0x12
 21a:	89 8b       	std	Y+17, r24	; 0x11

А вот мой:

  buffer[sizeof(buffer)-2] = lowByte(crc16);
 214:	84 ee       	ldi	r24, 0xE4	; 228
 216:	89 8b       	std	Y+17, r24	; 0x11
  buffer[sizeof(buffer)-1] = highByte(crc16);
 218:	8a ef       	ldi	r24, 0xFA	; 250
 21a:	8a 8b       	std	Y+18, r24	; 0x12

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Schwarz78 пишет:

И ваще - препроцессор зло. Хотя есть такие штуки, которые очень вкусные с препроцессором.

Сами Вы зло! Забыли классику?

"В "Си" ... введен  полезный  тип  данных  "указатель" (pointer). Получается,  как  будто  соединены  воедино  лучшие части языка Фортран и Ассемблера, не говоря уже о более творческих применениях оператора #DEFINE".

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я ахреневаю, дорогая редакция.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

ЕвгенийП пишет:

Я ахреневаю, дорогая редакция.

Иногда полезно своё ахреневание излить наружу. И вам легче, и волки целы.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

ЕвгенийП пишет:

Сами Вы зло! Забыли классику?

"В "Си" ... введен  полезный  тип  данных  "указатель" (pointer). Получается,  как  будто  соединены  воедино  лучшие части языка Фортран и Ассемблера, не говоря уже о более творческих применениях оператора #DEFINE".

Я же сказал - есть очень интересные мне вещи... С препроцессором.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Schwarz78 пишет:

 Так как Садаман никто для контроллеров не пишет. А вот почему у меня околесица? Я начинал с ассемблера, и примерно понимаю какой код даёт компилятор для 8-биток, а вы?

Тюююю.... Пишут еще как. Я так пишу, когда нужна переносимость. А она бывает нужна, что бы, кто бы не говорил. Да же если учесть что в ардуино IDE есть и DUE и  ESP с конца на конец.

И я начинал с ассемблера и мне кажется, что получится после компилятора... Но заметьте... Мне кажется, а вы прям так уверены :) 

Представить адрес куска байтового массива как адрес  какой нибудь 16 битной переменной, вполне себе нормальный подход. Будет быстрый и короткий код в результате.

А вот утверждать, что размер инта ДВА байта, я бы не стал :(

Schwarz78
Offline
Зарегистрирован: 19.01.2019

brokly пишет:

Тюююю.... Пишут еще как. Я так пишу, когда нужна переносимость. А она бывает нужна, что бы, кто бы не говорил. Да же если учесть что в ардуино IDE есть и DUE и  ESP с конца на конец.

И я начинал с ассемблера и мне кажется, что получится после компилятора... Но заметьте... Мне кажется, а вы прям так уверены :) 

Schwarz78 пишет:

Я начинал с ассемблера, и примерно понимаю

brokly пишет:

А вот утверждать, что размер инта ДВА байта, я бы не стал :(

Schwarz78 пишет:

Для 16-битного int, конечно.

Вот видите, если все мы будем внимательно читать и не вкладывать свои мысли в чужие ответы - будет гораздо больше взаимопонимания.
 
brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

А я не только для вас писал.... В любом случае в записях оперирующих значением указателя, ИМХО, следует избегать циферок связанных с размером данных, используйте sizeof ! Так по крайней мере будет понятен смысл написанного. 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

brokly пишет:

А я не только для вас писал.... В любом случае в записях оперирующих значением указателя, ИМХО, следует избегать циферок связанных с размером данных, используйте sizeof ! Так по крайней мере будет понятен смысл написанного. 

Ды тогда ты мне писал! ;)))

Тут "каждый дрочит, как он хочет" (с).

1.МК это не комп, если ты пишешь код под АВР, то его невозможно никуда перенести.

2. Проекты на МК - небольшие по объему, в силу того, что памяти в МК мало, следовательно автор у них один, он и тимлид, и кодер и тестер ;), читаемость для чего/кого? Для кота? ;)) (его Чавес зовут)

Если выкладывать ни гитхаб или для заказчика писать - тогда другое дело.

---------------

Ну и пункт три: там было написано: sizeof(uint16_t), а не просто int. Согласись, что узнавать размер 16 бит это уже немножко перебор, в отличии от  int.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Захотелось чуток дополнить

wdrakula пишет:
sizeof(uint16_t), а не просто int. Согласись, что узнавать размер 16 бит это уже немножко перебор, в отличии от  int.

На самом деле, узнавать размер int - тоже странновато. Что нам это даёт? Вон, например:

const size_t TotalItems = 20;
int items[TotalItems];

...........

// Вот так не стоит писать
qsort (items, TotalItems, sizeof(int), cmp);

// Вот так надо
qsort (items, TotalItems, sizeof(items[0]), cmp);

Если в какой-то момент поймём, что для items нам int не хватает и захотим поменять на long, то если написано sizeof(items[0]), то поменять тип достаточно в строке №2 и всё, а если написано sizeof(int), то надо не забыть ещё и в строке №7 поменять.

Общее правило: писать именно то, что тебя на самом деле интересует, а не использовать какие-то дополнительные знания об этом объекте. Интересует размер элемента массива - вот так и пишем, а уж int он там или ещё чего - какая разница?

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Евгений Петрович! Вот так, помаленечку, шажок за шажком и приучите нас к хорошему стилю )))

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ЕвгенийП пишет:

Общее правило: писать именно то, что тебя на самом деле интересует, а не использовать какие-то дополнительные знания об этом объекте. Интересует размер элемента массива - вот так и пишем, а уж int он там или ещё чего - какая разница?


А вот с этим я полностью согласен!

sadman41
Offline
Зарегистрирован: 19.10.2016

Коллеги, что ж вам этот sizeof(uint16_t) спать не дает... Я его написал для того, чтобы визуально сформировать у ТС понимание того, на сколько делать отступ назад от конца массива. Напиши 2 - пришлось бы объяснять, откуда эта константа и что код с ней тоже "так себе" по понимаемости. Я уже упоминал, что сам предпочитаю помещать crc через структуру - в этом случае вычисления смещений не требуются. Однако основной вопрос был про указатели, посему пришлось высасывать из пальца пример.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

wdrakula пишет:

Если выкладывать ни гитхаб или для заказчика писать - тогда другое дело.

Если пишешь для себя, то этого никто не должен видеть. А там действительно, кто как хочет. Можно хоть рисовать.

Вот правильнее всех Евгений написал. 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

brokly пишет:

Если пишешь для себя, то этого никто не должен видеть. А там действительно, кто как хочет. Можно хоть рисовать.

Вот правильнее всех Евгений написал. 

Если пишешь один, вы хотели сказать. И сам себе ОТК. Показывать можно, если не стыдно, вопрос ответственности, т.е. работает ли код, как надо. Если работает - вы молодец, если не работает - то все отмазки про чистоту языка, переносимость, красоту и новизну - не канают.

ЕвгенийП на то и профессор, чтобы правильно писать.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если не можешь писать правильно, пиши неправильно.©