видимо в прогмем только указатели, а строки в памяти
я всегда использую только второй вариант и код работает именно так, как предполагаю.
А первая запись мне интуитивно не нравится, когда вижу в чьем-то коде - передергивает слегка
Да это, вроде, с одной стороны объяснимо - разные адресные пространства и оба могут, в теории, начинаться с нуля.
Но простой тест показал, что строка при такой записи всё равно уходит в RAM:
void setup() {
Serial.begin(115200);
const char * yin PROGMEM = "789";
const char * yang PROGMEM = "123456789";
const char * dao PROGMEM = "456789";
Serial.print("*yin = 0x"); Serial.println((uint16_t) yin, HEX);
Serial.print("*yang = 0x"); Serial.println((uint16_t) yang, HEX);
Serial.print("*dao = 0x"); Serial.println((uint16_t) dao, HEX);
while (*dao) {
Serial.print((char) *dao);
dao++;
}
}
void loop (void) {}
Вобщем, потыкался и так и сяк - не выходит.
И не соображу, как раскладку по памяти посмотреть - avr-objdump -Ы мне что-то у elf-a не показывает секцию .progmem
Дак правильно, при таком обьявлении сама строка остается в ОЗУ, а в прогмем ты пхаешь указатель на неё.
Ну, можно же было помечтать…
Порылся в литературе, получается что эти две записи абсолютно эквивалентны для компилятора.
Однако я так понял, что первая более информативна в исходном коде, поскольку прямо указывает читателю (не компилятору, а читателю!), что функция работает не просто с указателем на единичную переменную, а с массивом
как сказать, я б подумал, что компилятор весь массив в стэк загоняет, чтобы функции передать. Поэтому стараюсь явно указатели указывать.
Да, господь с Вами!
Компилятору лишние контакты с ФСКН ни к чему.
не знал, спасибо.
а вот так:
void foo(“abcd”) ;
аналогично указатель передается?
Конечно.
Евгений, а еще вопрос
Правильно я понял, что при передаче размерного массива цифра размера ни на что не влияет?
void foo(char arr[10]) ;
Больше того, если в функции нужно размер массива узнать, то этот самый размер нужно вторым параметром передавать.
Влияет. Если указана, то в функции можно брать sizeof
, например.
В обычных функциях это не слишком важно, а вот в шаблонных - очень важно. Шаблон, он ведь генерирует функцию с типом параметра ,точно совпадающим с типом переданного аргумента. Поэтому, смотрите, функция из EEPROM.h
template< typename T > T &get( int idx, T &t ){
EEPtr e = idx;
uint8_t *ptr = (uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
return t;
}
ей можно передавать массивы и она отлично будет работать. Но именно массивы, а не указатели. Например:
//
// Правильно - тип второго параметра будет long [10]
// и get честно прочитает 40 байтов
//
long kaka[10];
...
get(eepAddr, kaka);
//
// Неправильно - тип второго параметра будет long *
// и get прочитает 2 байта
//
long * kaka = new long[10];
...
get(eepAddr, kaka);
Понятна разница?
Извините , это был не вопрос, просто проинформировал , что при такой попытки компилятор ругнулся , но после перегрузки иде все заработало. Поэтому уточнять какая ошибка вроде как небыло смысла(ответ то не нужен был ) А вобще я нашел в логах - warning: initializer-string for array of chars is too long [-fpermissive] , вот так он ругнулся на конструкцию
char TBuf[] = “000”;
Но как я говорил после перезагрузки глюк исчез…
Всем большое спасибо. частично с указателями разобрался ,а также наконец дошла мотивациея компилятора при обьеденении…
код работает нормально и вроде даже как самый наименьший по обьему в во флеш и рам…(из тех что мог придумать)
На такую строку он не мог так ругаться. Вот, если там у Вас между [ и ] была цифирь (например, 1 или 0), тогда да. Т.е. исчез он после того, как там цифирь исчезла. Я уж не говорю, что у Вас сейчас кавычки неправильные. Это ещё раз о том, что только копипаст!
Евгений Петрович, при всем уважении вы отвечали не на тот вопрос, что был задан (не исключаю и мою ошибку понимания вопроса). Но все же в функцию передастся указатель на массив символов, а не сам массив.
но тип этого указателя будет зависеть от цифр размера в квадратных скобках
То есть тип char [0] будет отличаться от char [10]? Почему?
Указатель указывает на начало области памяти, а что там дальше - решает программист. Разве нет?
Насколько я понимаю, в случае описания процедуры с явным указанием размера вы заранее сообщаете компилятору, что будете передать в процедуру именно массив размером 10, а не 2, к примеру. И эту информацию можно использовать, например для выделения памяти для временного буфера.
Правда я думал, что компилятор будет проверять размеры передаваемых массивов - ан нет, вот такой код даже предупреждений не генерирует:
int bb[2];
int foo(int aa[10]) {
return aa[8];
}
void loop() {
Serial.println(foo(bb));
}
А такой что говорит?