Сработает.COKPOWEHEU писал(а):А разве сработает?
Выделится в памяти константный массив символов (строка) и присвоится на неё указатель.
Сработает.COKPOWEHEU писал(а):А разве сработает?
Код: Выделить всё
volatile char p[]="AAA";
PORTB = p[1];
4e: 80 91 63 00 lds r24, 0x0063
52: 88 bb out 0x18, r24 ; 24Код: Выделить всё
volatile char *p="AAA";
PORTB = p[1];
4e: e0 91 62 00 lds r30, 0x0062
52: f0 91 63 00 lds r31, 0x0063
56: 81 81 ldd r24, Z+1 ; 0x01
58: 88 bb out 0x18, r24 ; 24А если прочитать данный пример повнимательнее? Или еще лучше - почитать букварь?COKPOWEHEU писал(а):Указатель не выделяет себе память при создании.
Во-первых, не в любом случае, а во-вторых - было явно указано: "Иногда и так бывает полезно. Хотя, это не общий случай.". Читайте внимательно прежде чем делать категоричные заявления.COKPOWEHEU писал(а):обращение к массиву в любом случае быстрее, чем к указателю
А где в примере было неявное определение типа?COKPOWEHEU писал(а):да и надежнее явно определять тип:
Это, всего-лишь потому, что p[] - указаеть-константа, адрес которой известен компилятору, а *p - указатель-переменная, из которой нужно ещё забрать адрес.COKPOWEHEU писал(а):Но обращение к массиву в любом случае быстрее, чем к указателю, да и надежнее явно определять тип:
Хотелось бы не голословные ругательства, а конкретные примеры.Pnjom-Penb писал(а):Во-первых, не в любом случае, а во-вторых - было явно указано: "Иногда и так бывает полезно. Хотя, это не общий случай.". Читайте внимательно прежде чем делать категоричные заявления.
Указатель вместо массива, очевидно.Pnjom-Penb писал(а):А где в примере было неявное определение типа?
Проверил:Аlex писал(а):Попробуйте подкинуть массиву переменный индекс, и у Вас код также развернётся в более чем 2 инструкции. В этом случае, обращение будет практически эквивалентно обращению через указатель.
Код: Выделить всё
volatile char *p="AAA";
volatile char str[]="BBB";
char i = PINB;
4e: 86 b3 in r24, 0x16 ; 22
PORTC = p[i];
5c: 99 27 eor r25, r25
5e: 87 fd sbrc r24, 7
60: 90 95 com r25
62: e0 91 64 00 lds r30, 0x0064
66: f0 91 65 00 lds r31, 0x0065
6a: e8 0f add r30, r24
6c: f9 1f adc r31, r25
6e: 20 81 ld r18, Z
70: 25 bb out 0x15, r18 ; 21
DDRC = str[i];
68: ff 27 eor r31, r31 //при другой компиляции, переменная i оказалась не в r24, а в r30
6a: e7 fd sbrc r30, 7
6c: f0 95 com r31
6e: e0 5a subi r30, 0xA0 ; 160
70: ff 4f sbci r31, 0xFF ; 255
72: 80 81 ld r24, Z
74: 84 bb out 0x14, r24 ; 20Код: Выделить всё
PORTC = *p;
5c: a0 91 64 00 lds r26, 0x0064
60: b0 91 65 00 lds r27, 0x0065
64: 8c 91 ld r24, X
66: 85 bb out 0x15, r24 ; 21Вот так вот, независимо ни от чего?COKPOWEHEU писал(а):Поэтому массив (строку) и стоит объявлять как массив, а не как указатель.
Вроде не бездельники
И могли бы жить,
Им бы указатели
Взять и отменить...
Опять же, не совсем правильное сравнение.COKPOWEHEU писал(а):Проверил:Как и следовало ожидать - обращение к массиву быстрее, чем к указателю, даже с переменным индексом.Код: Выделить всё
volatile char *p="AAA"; volatile char str[]="BBB"; char i = PINB; 4e: 86 b3 in r24, 0x16 ; 22 PORTC = p[i]; 5c: 99 27 eor r25, r25 5e: 87 fd sbrc r24, 7 60: 90 95 com r25 62: e0 91 64 00 lds r30, 0x0064 66: f0 91 65 00 lds r31, 0x0065 6a: e8 0f add r30, r24 6c: f9 1f adc r31, r25 6e: 20 81 ld r18, Z 70: 25 bb out 0x15, r18 ; 21 DDRC = str[i]; 68: ff 27 eor r31, r31 //при другой компиляции, переменная i оказалась не в r24, а в r30 6a: e7 fd sbrc r30, 7 6c: f0 95 com r31 6e: e0 5a subi r30, 0xA0 ; 160 70: ff 4f sbci r31, 0xFF ; 255 72: 80 81 ld r24, Z 74: 84 bb out 0x14, r24 ; 20
я имел в виду, сравнения типаВ этом случае, обращение будет практически эквивалентно обращению через указатель.
Код: Выделить всё
a = str[i];Код: Выделить всё
a = *p;Есть конечно. Когда массив - константная строка, которая никогда не изменится.COKPOWEHEU писал(а):Есть примеры, при котором выгоднее объявлять массив указателем-переменной?
Код: Выделить всё
char str[]="Мама мыла раму";
Код: Выделить всё
char* p="Мама мыла раму.";Код: Выделить всё
p="Мама домыла раму.";
......
Код: Выделить всё
char* const p="Мама мыла раму.";
......
p="Мама домыла раму."; // ОШИБКА !
я же приводил дизассемблерный код: второй вариант сработает быстрее, и его в некоторых случаях лучше использовать. Например, при копировании строк (strcpy), но это не объявление массива. Впрочем, если надо обрабатывать данные строго последовательно, это лучше, но и то, я бы записал какАlex писал(а):я имел в виду, сравнения типа a = str; и a = *p;Должно получится примерно одно и тоже.
Код: Выделить всё
char str[]="string"; //объявление и инициализация отдельно. Все равно, память занимается под данные, а не под их адрес, так что ничего не потеряем, зато сразу ясно что str - массив.
char *p=str; //обработка отдельноЗависит от компилятора. В avr-gcc и, вроде, cvavr, для размещения в ПЗУ есть специальный модификатор - PROGMEM, flash или как-то так. А уже для работы с существующей строкой можно использовать как указатель, так и прямой адрес (вот как это выглядит в avr-gcc)при том, что экземпляр строки уже где-то есть (вероятнее всего он во флеши) ?
Код: Выделить всё
PROGMEM char str[] = "string"; //опять объявление отдельно
char *p = str;
char dst[6];
memcpy_P(dst, p, 6); memcpy_P(dst, str,6); memcpy_P(dst, &str[2], 3); //использование отдельно
Так в чем преимущество? Зачем полагаться на то, что "компилятор будет сильно умным", если можно ему явным образом указать?Если не хотите случайно потерять ссылку на строку, либо не собираетесь дальше использовать этот указатель для других строк, то объявите указатель константой :
В таком случае, если компилятор будет сильно умным, есть вероятность, что он даже память не будет выделять под указатель, а просто будет заменять его сразу на адрес строки.
Я не доказывал преимущества массивов во всех случаях. Я доказывал только то, что объявление строки через массив лучше, чем через указатель.для чего-то доказывая, что указатели - плохо, а массивы - хорошо, подбирая какие-то варианты, где с указателем код становится жирнее
Ни от чего это не зависит. Строка в массив откуда то копируется (пусть даже байтами по-очереди, командами в ряд), а значит она занимает память. И причём тут PROGMEM ? Речь совсем не о том, где размещается строка. А о том, что она уже где-то есть.COKPOWEHEU писал(а):Зависит от компилятора. В avr-gcc и, вроде, cvavr, для размещения в ПЗУ есть специальный модификатор - PROGMEM
Вы, по всей видимости, меня не поняли. Не надо ни на кого полагаться, это я для примера сказал, если ссылку не хотите терять.COKPOWEHEU писал(а):Так в чем преимущество? Зачем полагаться на то, что "компилятор будет сильно умным", если можно ему явным образом указать?
Объявление строки, с присваиванием указателя на неё ничем не отличается от присваивания её массиву. Строка не объявляется через чего-то, она объявляется в виде текста, обрамлённого кавычками. Когда Вы пишете в коде "Строка", она уже объявлена ,и под неё уже выделено место. Единственное, когда Вы объявляете ещё и массив, она тупо копируется в него.COKPOWEHEU писал(а):Я доказывал только то, что объявление строки через массив лучше, чем через указатель.
Зачем мне проверять очевидные вещи ? Что Вы вообще прицепились к этим областям хранения ? Речь не о том, что и где лежит - это уже другая тема, к которой Вы потихоньку перебираетесь, уходя от основной темы разговораСами бы проверили в отладчике, что и где хранится
Если она объявлена как размещенная в ПЗУ, автоматически копироваться в ОЗУ она не будет, и не займет там ни одного байта.Аlex писал(а):Ни от чего это не зависит. Строка в массив откуда то копируется (пусть даже байтами по-очереди, командами в ряд), а значит она занимает память. И причём тут PROGMEM ? Речь совсем не о том, где размещается строка. А о том, что она уже где-то есть.
Вот именно. Объявление массива не создает лишних переменных. То есть запись char str[]="AAA"; занимает 4 байта, а запись char *p="AAA"; - 6 байт (для AVR, где указатель двухбайтный).Аlex писал(а):Преимущество в том, что Вы под строку, которая никогда не будет меняться, занимаете ещё драгоценное ОЗУ, объявляя массив. А зачем он Вам в этом случае ? Вам только строка нужна, которая итак уже где-то лежит. Дак почему бы её оттуда и не забирать ?
Объявление массива само по себе места не занимает, как и объявление переменной. Место резервируется под данные. В случае указателя, отдельно резервируется место и под строку (причем, по умолчанию, в ОЗУ), и под ее адрес.Аlex писал(а):Объявление строки, с присваиванием указателя на неё ничем не отличается от присваивания её массиву. Строка не объявляется через чего-то, она объявляется в виде текста, обрамлённого кавычками. Когда Вы пишете в коде "Строка", она уже объявлена ,и под неё уже выделено место. Единственное, когда Вы объявляете ещё и массив, она тупо копируется в него.
Знаете, у меня закрадываются схожие сомнения на ваш счет. Впрочем тут мы можем сравнить компетентность друг друга. Есть записиАlex писал(а):У меня начинается складываться впечатление о Вашей некомпетентности в этой области. Очень надеюсь, что ошибаюсь.
Код: Выделить всё
char rstr[] = "RAM str";
char *rptr = "RAM ptr";
PROGMEM const char fstr[] = "ROM str";
PROGMEM const char *fptr = "ROM ptr";
char *fptr2 = PSTR("ROM PTR");Потому что, как показало это обсуждение, эти вещи не очевидны. А от какой темы я ухожу? Пока что я общаюсь на тему "преимущества объявления строки как массива перед указателем".Аlex писал(а):Зачем мне проверять очевидные вещи ? Что Вы вообще прицепились к этим областям хранения ? Речь не о том, что и где лежит - это уже другая тема, к которой Вы потихоньку перебираетесь, уходя от основной темы разговора
Ну, 8 байт флеши уйдет на одну строку, обсуждение у нас о прочих расходах.Скажу только то, что знаю точно. char rstr[] = "RAM str"; займёт минимум 8 байт флеши
скорее всего проблема в описании массива text - каков его размер?fatall_error писал(а):Народ помогите!!! не получается вывести на LCD строку в Протеусе
о чем вы спорите, о каких волнах идет речь? записи char *s и char s[] полностью идентичны по всем формальным критериям! это даже не совсем разные записи одного и того же. а то, что в определенный момент вы инициализируете указатель адресом какой-то строки, это дело третье.Аlex писал(а):Что бы мы общались "на одной волне"