Перейти к содержанию
    

Мое мнение - для массива &mass и mass - одно и то же.
Не совсем. &mass[0] и mass - вот это одно и то же. Точнее mass неявно приводится к &mass[0].

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверьте на том, что имеете.

Мое мнение - для массива &mass и mass - одно и то же. Особенность языка.

В IARе я так много раз делал без замечаний. Но если 5-ый Keil ругается на явное преобразование адреса от имени структуры без амперсанда, то использование аналогичного синтаксиса к имени массива порождает другой глюк. Кейлу логично было бы запретить использование (void *)&mass. Иначе будут новые грабли.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кейлу логично было бы запретить использование (void *)&mass.

Наверное, так оно и есть.

 

Проверил. Получил.

uint16_t arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

uint16_t *parr = &arr;

 

source\Exercises.c(159): error: #144: a value of type "uint16_t (*)[10]" cannot be used to initialize an entity of type "uint16_t *"

 

На uint16_t *parr = &arr[0]; не ругается, естественно.

 

На uint16_t *parr = (uint16_t *)&arr; тоже не ругается!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На uint16_t *parr = (uint16_t *)&arr; тоже не ругается!
Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Естественно. Вы же делаете явное приведение типа. В этом случае каждый сам себе злобный Буратина, а компилятор умывает руки - если вы его просите о таком, значит знаете, чего хотите.

Значит, компилятор "имеет представление" о том, что такое &arr. Почему же он неявное приведение не делает?

Ассемблерные команды получаются те же, что и для uint16_t *parr = arr;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почему же он неявное приведение не делает?
Потому что таковы правила языка. Это называется "безопасность типов" (type safety). Он не даем вам случайно спутать теплое с мягким и мух с котлетами. Но и оставляет вам право сделать это, если вам это действительно нужно, через явное приведение типов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В процессорах с Гарвардской архитектурой AVR, PIC, 8051 константы размещаются во флеше. Флеш расположен в другом адресном пространстве чем ОЗУ и используются другие ассемблерные команды для доступа. Разумно расположить константные массивы во флеше, поскольку если располагать их в ОЗУ, то будут использована и флеш тоже (откуда-то ведь будет инициализация читаться). Передавая такой параметр в функцию надо дать знать в каком пространстве памяти находится параметр, чтобы функция использовала правильные ассемблерные команды.

Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе. С другими не работал не знаю.

Изменено пользователем Tarbal

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В процессорах с Гарвардской архитектурой AVR, PIC, 8051 константы размещаются во флеше.
Ну вот где вы такое видели применительно к языку C в реальном мире? Квалификатор const лишь дает гарантию, что компилятор не допустит изменения переменной с таким квалификатором. И никоим образом не влияет на адресное пространство. Если вы объявили переменную с квалификатором const - под нее точно так же будет выделено место в ОЗУ.

вот вам простой пример:

char string1[] = " string1";
char const string2[] = "string2";

void print_string(char const * string) // const тут гарантирует, что функция не изменит переданную ей строку
{
   .........

    string[0] = '+';  // компилятор даст по рукам. В объявлении параметра мы обещали, что не будем его менять
}

void empty_string(char * string) // а вот тут гарантий нет, переданная строка может быть изменена.
{
   .........
    string[1] = '+';  // пожалуйста
}

void test()
{
     print_string(string1);   // да без проблем, в соответствии с правилами языка
     print_string(string2);   // тоже запросто

     empty_string(string1); // легко
     empty_string(string2); // нифига. const в объявлении string2 запрещает, функция может модифицировать строку

     string1[0] = "!";  // да, пожалуйста
     string2[0] = "x"; // а вот фиг
}

А теперь объясните, каким образом print_string() будет понимать - ей передали указатель на строку во флеше или на строку в ОЗУ?

 

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

 

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

Для этого и используется слово const. Pic использует слово flash кажется, но это в микрочиповском компиляторе.

Нет. слово const используется для другого. Как раз слово flash явлается расширением языка - квалификатором адресного пространства и используется именно для этого.

 

А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.

А каким образом это делается? Буквально в двух словах, если можно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А вот в процессорах с единым адресным пространством (ARM, x86, MSP430) досуп к переменным во флеше или в ОЗУ на чтение одинаков, поэтому именно в них возможно указать линкеру размещать константные переменные во флеше не загружая копию в ОЗУ. А можно указать хранить в ОЗУ и все будет как у больших машин.

Есть способ - указать квалификатор static.

static const uint8_t *SourTxt[] = {"Кан1", "Кан2"};

В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При чём тут static вообще? На ARMах const в определении переменной заставляет компилятор (и линкер) размещать её во флэше. На AVR такое не работало из-за раздельного адресного пространства.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использование ключевых слов static и/или const для управления размещением данных (будь то flash или еще что) - вещь на 100% зависящая от конкретного компилятора. Стандарт С/С++ вообще не знает о том, что такое flash и как в нее помещать данные :)

 

Поэтом, прежде чем советовать что то типа

Есть способ - указать квалификатор static.

В ОЗУ этих строк не будет. Сразу будут читаться из флэш программы.

стоит указать, для каких именно компиляторов это справедливо

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

для каких именно компиляторов

Ни для каких. static очевидно может изменяться во время выполнения программы и не может быть размещён во flash.

const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поэтом, прежде чем советовать что то типа

стоит указать, для каких именно компиляторов это справедливо

Для компилятора, входящего в состав Keil uVision. Пользуюсь этими квалификаторами.

О каком компиляторе идет речь, видно в теме неоднократно.

 

 

static очевидно может изменяться во время выполнения программы и не может быть размещён во flash.

const размещает переменные во flash независимо от квалификатора static - актуально для IAR для ARM.

static const

Строка просто const из flash переписывается в ОЗУ, и уже из ОЗУ используется в функции. Лично сталкивался. И получал на форуме совет. И от кого, помню.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что, вашему компилятору не хватает ума разместить глобальную переменную во флэше? Или вы просто не пробовали?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...