Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

Напротив. Компилятор всегда знает количество числа в масиве.
Так нечестно, давайте такой пример:

Код: Выделить всё

void Dummy(const int8[] data)
{
    int n = sizeof(data); // Чему равно n?
}
void main()
{
    const int8 a[] = {11, 22, 33, 44, 55};
    Dummy(a);
}
veso74
Поставщик валерьянки для Кота
Сообщения: 1902
Зарегистрирован: Сб май 05, 2012 20:24:52
Откуда: KN34PC, Болгария
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение veso74 »

(Упс, тема про AVR :) ).
---
azhel12, да, с констант является ложным примером. sizeof врёт :) Кроме в препроцессора, где вычисляется перед компиляцией. Спасибо!

Код: Выделить всё

const int a[] = {11, 22, 33, 44, 55};
int n = sizeof(a) / sizeof(int);

int Dummy(int *data) {
  return (sizeof(data));
}

void setup() {
  Serial.println(Dummy(a));
  Serial.println(n);
}

ответ:
Последний раз редактировалось veso74 Сб окт 22, 2022 16:30:54, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

[uquote="ARV",url="/forum/viewtopic.php?p=4308233#p4308233"]но Си и С++ никогда не сделают так, будут жрать кактус...
Просто в C/C++ иногда приходится обрабатывать строки длиной больше 255 символов...[/uquote]
времена, когда одного байта было достаточно для любого символа, давно миновали... сейчас для строк уже используются 2-байтные символы, а если речь о кодировке UTF - то и трех, четырех и даже может быть больше байтов на символ... в связи с чем "нулевой символ" паскалевской строки давно имеет тип integer, т.е. на 32-битных машинах строка может быть порядка 2Г длиной, а на 64-битных и того больше...
VladislavS писал(а):В С++ есть класс std::string. Можете поинтересоваться на досуге как он устроен, особенно в последних стандартах
хорош же стандарт, который от версии к версии меняется так кардинально...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение VladislavS »

хорош же стандарт, который от версии к версии меняется так кардинально...
Зачем вы пишете о том в чём вообще ничего не понимаете? Внутреннее устройство строки пользователя не должно сильно волновать, а лишь интерфес, который от стандарта к стандарту остаётся неизменным. Добавляются лишь новые свойства поведения в константном окружении, оптимизации строк малого размера и т.д. Если программист знает новые возможности - хорошо, нет - и со старыми переживёт. Тем более, что в основном это забота компилятора. Так что, не придумывайте проблему там где её нет. Нультерминированные С-строки, впрочем, в плюсах тоже никто не запрещал.
Аватара пользователя
Just_Fluffy
Вымогатель припоя
Сообщения: 532
Зарегистрирован: Ср июн 29, 2022 16:25:45

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Just_Fluffy »

Вот честно, сишные нуль-терминированные строки бесят.
Бесят именно тем, что символ с кодом ноль - которй по сути - тоже символ, один из 256, в стандартную строку записать нельзя.
Паскалевские строки в этом плане всеядны.
Белая и Пушистая
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение ARV »

кстати, я последнее время паскалевские строки вообще для любых данных применяю. например, делал прошивальщик с шифрованием, так там по определению данные бинарные, но удобнее строк ничего не нашлось.
эх, хорошо! :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

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


Нет, паскалевские строки точно так же кривы, как и сишные строки. Только с другого конца.

Добавлено after 2 minutes 10 seconds:
[uquote="veso74",url="/forum/viewtopic.php?p=4308297#p4308297"]Напротив. Компилятор всегда знает количество числа в масиве.
Так нечестно, давайте такой пример:

Код: Выделить всё

void Dummy(const int8[] data)
{
    int n = sizeof(data); // Чему равно n?
}
void main()
{
    const int8 a[] = {11, 22, 33, 44, 55};
    Dummy(a);
}
[/uquote]

Это не относящийся к делу пример. Здесь в месте применения sizeof нет массива (даже если закрыть глаза на синтаксические ошибки в объявлении параметра). А исходное утверждение о sizeof было именно о массиве.

sizeof возвращает размер массива только тогда, когда применен именно к массиву. Если вы будете применять sizeof к указателю, размер массива вы, разумеется, не получите. Если вы хотите, чтобы sizeof продолжал возвращать размер массива - следите за тем, чтобы массив оставался массивом, т.е. не позволяйте ему деградировать до указателя.
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

Это не относящийся к делу пример. Здесь в месте применения sizeof нет массива.
Абсолютно согласен, сделал подобное упрощение исключительно для демонстрации того, что все равно без передачи размера не обойтись, если только речь не идет о глобальных массивах или записи всей программы в функцию main. Просто в C/C++ невозможно объявить параметр для передачи массива, кроме как сделать его указателем.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение VladislavS »

В C++ есть std::array. Его можно как параметр без указания размера передавать. Только не уверен, что для AVR его завезли.
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

Просто в C/C++ невозможно объявить параметр для передачи массива, кроме как сделать его указателем.


В С и С++ нет возможности передачи голого массива по значению.

Тем не менее, если рассматривать только "ссылочные" способы передачи (т.е. "по указателю" или "по ссылке"), то возможность передать массив без потери типа "массив" (и его размера) у вас всегда есть

Код: Выделить всё

#include <stdio.h>

void foo(int (*a)[10])
{
  printf("%zu\n", sizeof *a / sizeof **a);
  (*a)[5] = 42;
}

void bar(int (&a)[10]) // С++
{
  printf("%zu\n", sizeof a / sizeof *a);
  a[6] = 42;
}

int main(void)
{
  int a[10];
  foo(&a);
  bar(a); // C++
  printf("%d %d\n", a[5], a[6]);
}


Разумеется, в такой ситуации размер массива остается просто свойством типа, т.е. заведомо известной и фиксированной характеристикой времени компиляции (пока мы не лезем в VLA в языке С).

Добавлено after 5 minutes 27 seconds:
В C++ есть std::array. Его можно как параметр без указания размера передавать. Только не уверен, что для AVR его завезли.


`std::array` - это не более чем struct-обертка для массива. Не составит труда сделать и самостоятельно, в том числе в С. Но, как вы сами понимаете, нам сейчас расскажут, что "это не то", так как функция, работающая с завернутым массивом (как и функции из моего примера выше), привязаны к конкретному размеру массива.

Однако что вы имеете в виду под "без указания размера" - не ясно. Спецификация шаблонного типа `std::array` всегда включает размер. То есть передавать его вы будете примерно так

Код: Выделить всё

void foo(std::array<int, 8> array)
{
  ...
}


Как видите, размер там явно указан.
Последний раз редактировалось KorbenDallas Вт окт 25, 2022 01:35:28, всего редактировалось 2 раза.
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

`std::array` - это не более чем struct-обертка для массива.
Это не так. В std::array размер - это шаблонный параметр, то есть каждая пара <тип, размер> порождает новый тип данных. И функция, которая собирается принимать std::array становится шаблонной (то есть снова для каждой пары <тип, размер> компилятор генерирует отдельную специализацию).
Это вообще говоря сахар над обычными статическими массивами, можно и без std::array обойтись:

Код: Выделить всё

template<typename Type, int Size>
void F(Type (&data)[Size])
{
    data[6] = Type();
}
// Ну или для int
template<int Size>
void G(int (&data)[Size])
{
    data[6] = 42;
}
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

[uquote="KorbenDallas",url="/forum/viewtopic.php?p=4309501#p4309501"]`std::array` - это не более чем struct-обертка для массива.
Это не так.[/uquote]

Это абсолютно так. Стандарт языка не утверждает этого открытым текстом, но открытые требования спецификации делают это фактически неизбежным (т.е. агрегат, structural-тип, списковая инициализация и т.п.) и традиционные реализации пользуются именно массивом внутри struct.

В std::array размер - это шаблонный параметр, то есть каждая пара <тип, размер> порождает новый тип данных.


Это прекрасно, но при чем здесь это? Да, это шаблон. Это именно шаблон для массива, завернутого в структуру. Параметры шаблона "тип" и "размер" становятся типом элементов этого массива и его размером. Где вы здесь увидели противоречие с тем, что я сказал выше?

Да и для обычного голого массива я могу сделать тип и размер шаблонными параметрами

Код: Выделить всё

template <typename T, std::size_t N> using naked_array_type = T [N];


Готово. Теперь `naked_array_type<double, 42>` - это синоним `double [42]`.

Так что шаблонность тут сбоку припеку. Она ничего не меняет.

И функция, которая собирается принимать std::array становится шаблонной (то есть снова для каждой пары <тип, размер> компилятор генерирует отдельную специализацию).


Что значит "становится шаблонной"? Нет, она не "становится шаблонной". Это вы ее можете сделать шаблонной, если захотите один раз написать код для разных типов и/или размеров. А можете и не делать этого. Это ваше решение.

Это вообще говоря сахар над обычными статическими массивами,


Совершенно верно. Как я сказал выше, это `std::array` - это синтаксический сахар над обычным массивом, завернутым в struct.

(Я также не понимаю такого использования термина "статический". Термин "статический" уже занят в С и С++ для других целей, т.е. для обозначения статического класса хранения. Поэтому откуда лезет вот эта странная манера называть обычные массивы "статическими" мне не ясно. Не ясно также, почему ораторы не понимаю проблемы с таим использованием уже занятого термина.)

можно и без std::array обойтись:


Это само собой разумеется, но уже мимо темы. Я включился в обсуждение `std::array`именно как варианта полноценного "массивного" типа, то есть копируемого типа, который можно в том числе присваивать и передавать/возвращать по значению. Именно об этом идет речь. Ваши шаблонные варианты с голыми массивами не делают массивы копируемыми и не позволяют передавать их по значению.

Классическим, старым как мир, С/С++ трюком для реализации копируемого массива является обертка голого массива в struct. `std::array` - это как раз С++ адаптация (под контейнерный интерфейс) этого самого трюка. Ни больше, ни меньше.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение VladislavS »

Код: Выделить всё

#include <iostream>
#include <array>

void foo(auto arr)
{
  for(auto &x: arr) std::cout << x << ' ';
}

std::array<int,4> a = {1,2,3,4};
std::array<int,5> b = {5,6,7,8,9};

int main()
{
  foo(a);
  foo(b);
  return 0;
}
Compiler Explorer
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

традиционные реализации пользуются именно массивом внутри struct.
Возможно, мы друг друга не очень поняли, я имел ввиду, что std:array не имеет отдельного поля с размером, по крайней мере традиционные реализации (можно спорить по поводу традиций, но я посмотрел варианты msvc и gcc). Определение же метода size() очень простое: return _Size;, где _Size - шаблонный параметр.


Нет, она не "становится шаблонной"
Ок, можно пример кода, как принять объект std::array не делая функцию шаблонной?

Поэтому откуда лезет вот эта странная манера называть обычные массивы "статическими" мне не ясно.
По-моему такой термин действительно прижился, статический в смысле его размера, известного во времени компиляции. Можем назвать такие массивы "не-динамическими" или "автоматическими", но нас не поймут.


Обозначение параметров как auto - это тоже обертка над шаблонами, прикладываю скрины с самого godbolt.org, компилятор сгенерировал две функции-специализации.

Изображение

Изображение
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

Код: Выделить всё

void foo(auto arr)
{
  for(auto &x: arr) std::cout << x << &#39; &#39;;
}


Вы не написали функцию, вы написали шаблон функции, точно также как это сделал предыдущий оратор. Шаблоны - тема совершенно ортогональная. Я не совсем понимаю, зачем вы начали тянуть сюда шаблоны и что вы пытаетесь ими продемонстрировать.

Шаблоны функций - не функции. Шаблоны функций будут лишь использоваться для "штамповки" функций. Для каждой комбинации размера и типа элемента `std::array` будет сгенерирована своя отдельная функция. Точно так же, как мы могли это сделать руками.

Другими словами шаблоны никак не помогут вам победить твердое правило: тип элемента и размер массива всегда будет жестко прописан в типе параметра функции.

Добавлено after 3 minutes 6 seconds:
[uquote="KorbenDallas",url="/forum/viewtopic.php?p=4309571#p4309571"]традиционные реализации пользуются именно массивом внутри struct.
Возможно, мы друг друга не очень поняли, я имел ввиду, что std:array не имеет отдельного поля с размером[/uquote]

Разумеется, не имеет. Зачем оно ему? Точно так же как и обычный массив не имеет отдельного поля с размером. `std::array` - совершенно бесплатная обертка над массивом. Она имеет нулевой оверхед и по памяти, и по коду.

Откуда вообще возникла тема "отдельного поля с размером"? Я пока не замечал, чтобы кто-то об этом говорил.

[uquote="KorbenDallas",url="/forum/viewtopic.php?p=4309571#p4309571"]Нет, она не "становится шаблонной"
Ок, можно пример кода, как принять объект std::array не делая функцию шаблонной?[/uquote]

Странный вопрос. Пожалуйста

Код: Выделить всё

void foo(std::array<int, 8> a)
{
}
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

Откуда вообще возникла тема "отдельного поля с размером"
Я так подумал после слов об обёртке над структурой с массивом. Что тогда в этой структуре кроме самого массива есть?

Код: Выделить всё

void foo(std::array<int, 8> a)
{
}
Видимо, мы говорили об одном и том же, что невозможно для std::array в рантайме получить размер.
Касаемо приведённого кода, сомнительная ценность функции, которая применима для фиксированного размера, поэтому и говорил, что использование std::array вынуждает писать шаблонные функции (оверхед переехал).
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

[uquote="KorbenDallas",url="/forum/viewtopic.php?p=4309620#p4309620"]Откуда вообще возникла тема "отдельного поля с размером"
Я так подумал после слов об обёртке над структурой с массивом. Что тогда в этой структуре кроме самого массива есть?[/uquote]

Абсолютно ничего. Только массив. В этом вся идея. Нулевой оверхед во всех отношениях.

Как я говорил выше, основная цель оборачивание массива в структуру - сделать его копируемым, то есть передаваемым/возвращаемым по значению и присваиваемым. В С и С++ голые массивы некопируемы, а вот массивы, завернутые в структуры - прекрасно копируемы.

Видимо, мы говорили об одном и том же, что невозможно для std::array в рантайме получить размер.


Разумеется, невозможно. `std::array` ничем не отличается от голого массива, кроме копируемости.

Касаемо приведённого кода, сомнительная ценность функции, которая применима для фиксированного размера, поэтому и говорил, что использование std::array вынуждает писать шаблонные функции (оверхед переехал).


Это то, о чем я уже говорил выше. Абстрактная/универсальная функция работы с массивами такого вида действительно имеет сомнительную ценность. Конкретная же функция работы с конкретным application-specific типом данных - имеет прекрасную ценность. Если функция в шахматной программе берет на вход `std::array<std::array<int, 8>, 8>` ничего "сомнительного" в этом нет. Если функция работы с cетевыми протоколами принимает `std::array<uint8_t, 4>` ничего "сомнительного" в этом нет.
Аватара пользователя
azhel12
Встал на лапы
Сообщения: 145
Зарегистрирован: Пн апр 02, 2012 15:56:23

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение azhel12 »

Разумеется, невозможно. `std::array` ничем не отличается от голого массива, кроме копируемости.
Про копируемость я до сих пор не задумывался, действительно. Спасибо, что просветили!
Аватара пользователя
Jack_A
Друг Кота
Сообщения: 6307
Зарегистрирован: Вт апр 24, 2007 07:45:40
Откуда: Minsk

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение Jack_A »

Простите великодушно старого ретрограда, но не смог сдержаться.
Если читать посты, не прочитав заглавие раздела, то создалось бы впечатление, что речь идёт о мега-ПК с гигабайтами ОЗУ. На мой (устаревший) взгляд, для AVR простого Си хватит и даже с избытком. Шаблоны, классы, инкапсуляция... для Тини2313 :shock:
СпойлерЧто-то там говорили об воробьях и о пушках ?
Изображение
Аватара пользователя
KorbenDallas
Встал на лапы
Сообщения: 93
Зарегистрирован: Пн окт 31, 2016 06:23:19

Re: Нескольно простых вопросов о программировании AVR на Си.

Сообщение KorbenDallas »

Простите великодушно старого ретрограда, но не смог сдержаться.
Если читать посты, не прочитав заглавие раздела, то создалось бы впечатление, что речь идёт о мега-ПК с гигабайтами ОЗУ.


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

"Гигабайты ОЗУ" для переваривания всего этого нужны той платформе, на которой будет производиться компиляция. Ну так у нее то они как раз таки есть.
Ответить

Вернуться в «AVR»