|
|
  |
процедура с указателем на строку в памяти программ, помогите разобраться |
|
|
|
Dec 25 2008, 12:49
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(demiurg_spb @ Dec 25 2008, 14:11)  Примеры компиляторов? Это небось только узкоспециализированные и заточенные под мало разрядные MCU. Я солидарен с zltigo и в основном всегда char знаковый. Проведите аналогию с int. Да, полностью согласен с Вами и Zltigo. Это мое воинствующее невежество выстрелило  Чтобы закрыть тему с char приведу цитату из описания на gcc: Цитата Each kind of machine has a default for what `char' should be. It is either like `unsigned char' by default or like `signed char' by default.
Ideally, a portable program should always use `signed char' or `unsigned char' when it depends on the signedness of an object. But many programs have been written to use plain `char' and expect it to be signed, or expect it to be unsigned, depending on the machines they were written for. This option, and its inverse, let you make such a program work with the opposite default.
The type `char' is always a distinct type from each of `signed char' or `unsigned char', even though its behavior is always just like one of those two.
|
|
|
|
|
Dec 25 2008, 13:37
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(rezident @ Dec 25 2008, 15:35)  Я с вами согласен, что нужно писать так, чтобы типы приводить не приходилось. Но я-то писал в применении к конкретному коду, а не к коду "вообще" или "в принципе". Именно тут - да, можете. А что произойдет в случае сравнения на больше/меньше? Тоже будете уповать на то, что по-умолчанию char как unsigned char используется? Я уповать не буду. Мне вообще всё равно что за тип char (со знаком или без) и всем остальным это должно быть тоже безразлично. Ибо его надо использовать только для работы с текстовыми строками и символами. Я легко и непринуждённо буду писать Код char ch = '0'; .... ch++; ... if ((ch>='0')&&(ch<='9')) {} и даже не вспомню о надуманной проблеме знака. Все прекрасно будет работать и именно так как я хочу. В развитие темы хочу добавить, что когда я вижу код Код for (char i=0; i<N; i++) {} // так писать нельзя я никак не могу избавится от желания отшлёпать автора такого кода. Лень написать unsigned char так используйте тип uint8_t. Код #include <stdint.h> for (uint8_t i=0; i<N; i++) {} Но осознанно создавать неопределённое поведение программы - это по меньшей мере неблагоразумно.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 25 2008, 13:44
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(chief_olimp @ Dec 25 2008, 14:18)  Скажите у Вас у самого код что сверху работает со словами из FLASH? Конкретно этот не проверял, но если в pgmspace.h описан прототип extern char *strstr_P(const char *, PGM_P); то у меня нет основания сомневаться в том, что первый агрумент - указатель на строку в ОЗУ, а второй - на строку в flash. Описание стандартной функции strstr гласит: Цитата Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1. А это именно то, что требуется, судя по вашему исходнику. Цитата(chief_olimp @ Dec 25 2008, 14:18)  Мой код у меня работает и меня лично вполне устаивает. Весьма сомнительно - в вашем коде нет обращения к flash. Цитата(chief_olimp @ Dec 25 2008, 14:18)  Код что выше у меня не работает, и выдает ошибку что не понимает аттрибута функции. Тренировки в телепатии, безусловно, полезны. Но пока мы не достигли совершенства в этой области неплохо было бы приводить конкретную строку, на которую выдается ошибка и конкретный текст ошибки. Мой код прекрасно компилируется: CODE main.cpp: #include <avr\pgmspace.h> char USART0_InBuf[10]; int fndOK; void find(prog_char const * inb) { prog_char const * found = strstr_P(USART0_InBuf, inb); if (!found) fndOK=-1; else fndOK = found - USART0_InBuf; }
main.lst: 531 .section .text._Z4findPKc,"ax",@progbits 532 .global _Z4findPKc 534 _Z4findPKc: 535 .LFB37: 536 .LSM79: 537 /* prologue: frame size=0 */ 538 /* prologue end (size=0) */ 539 .LVL13: 540 .LBB23: 541 .LSM80: 542 0000 BC01 movw r22,r24 ; inb, inb 543 0002 80E0 ldi r24,lo8(USART0_InBuf) ; , 544 0004 90E0 ldi r25,hi8(USART0_InBuf) ; , 545 .LVL14: 546 0006 00D0 rcall strstr_P ; 547 .LVL15: 548 .LSM81: 549 0008 0097 sbiw r24,0 ; found 550 .LVL16: 551 000a 01F4 brne .L64 ; , 552 .LSM82: 553 000c 8FEF ldi r24,lo8(-1) ; tmp45, 554 000e 9FEF ldi r25,hi8(-1) ; tmp45, 555 .LVL17: 556 0010 00C0 rjmp .L68 ; 557 .LVL18: 558 .L64: 559 .LSM83: 560 0012 8050 subi r24,lo8(USART0_InBuf) ; found, 561 0014 9040 sbci r25,hi8(USART0_InBuf) ; found, 562 .L68: 563 0016 9093 0000 sts (fndOK)+1,r25 ; fndOK, found 564 001a 8093 0000 sts fndOK,r24 ; fndOK, found 565 001e 0895 ret 566 .LBE23: 567 /* epilogue: frame size=0 */ 568 /* epilogue: noreturn */ 569 /* epilogue end (size=0) */ 570 /* function void find(const prog_char*) size 16 (16) */
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 25 2008, 14:22
|

Местный
  
Группа: Участник
Сообщений: 249
Регистрация: 31-10-05
Из: Украина Нетешин
Пользователь №: 10 344

|
Обращение есть. CODE void find (const void *findbuff) { findOK = false; unsigned int i=0; unsigned char temp,j=0; pointer = 0; while(1) { temp = pgm_read_byte(findbuff++); if(temp==0) break; FIND[i++] = temp; } i=0; while (i != USART0_InBufSize) { if (USART0_InBuf[i] == FIND[j]) { i++;j++;findOK = true; if (FIND[j] == 0x00) { pointer = i; break; } } else { i++; if (findOK == true) { i = i-j; j=0; findOK = false; } } } } Но перед вами снимаю шляпу. Три страницы нужно было исписать что бы прийти к трем строчкам текста
|
|
|
|
|
Dec 25 2008, 14:31
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(demiurg_spb @ Dec 25 2008, 16:37)  Я легко и непринуждённо буду писать... И это правильно. Почти всегда правильно  без кирилицы... Цитата В развитие темы хочу добавить, что когда я вижу код Код for (char i=0; i<N; i++) {} // так писать нельзя я никак не могу избавится от желания отшлёпать автора такого кода. Лень написать unsigned char так используйте тип uint8_t. Код #include <stdint.h> for (uint8_t i=0; i<N; i++) {} И за то, что Вы написали, надо больно шлепать, если это перенести не на восьмибитовик  . Исправитесь?
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 25 2008, 15:00
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(demiurg_spb @ Dec 25 2008, 18:37)  и даже не вспомню о надуманной проблеме знака. Все прекрасно будет работать и именно так как я хочу. Будет работать до тех пор, пока вы используете только первую половину ASCII или KOI-7 и не используете в строковых переменных кириллицу. О чем я выше уже упомянул. Цитата(demiurg_spb @ Dec 25 2008, 18:37)  Лень написать unsigned char так используйте тип uint8_t. Вообще-то в качестве автоматических переменных цикла принято использовать тип int или unsigned int. А типы uint8_t, uint16_t и прочие подобные им не являются полностью стандартными, т.к. появились лишь как расширение в C99 и отсутствовали в ANSI C (хотя здесь могу и ошибаться, т.к. я не слишком большой знаток истории развития языка Си).
|
|
|
|
|
Dec 25 2008, 16:38
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(rezident @ Dec 25 2008, 18:00)  Будет работать до тех пор, пока вы используете только первую половину ASCII или KOI-7 и не используете в строковых переменных кириллицу. О чем я выше уже упомянул. Вообще-то в качестве автоматических переменных цикла принято использовать тип int или unsigned int. А типы uint8_t, uint16_t и прочие подобные им не являются полностью стандартными, т.к. появились лишь как расширение в C99 и отсутствовали в ANSI C (хотя здесь могу и ошибаться, т.к. я не слишком большой знаток истории развития языка Си). Это программа для AVR и тут int не то чтобы сильно подходит. Я использую не только первую половину ASCII... Код //============================================================================= unsigned char is_rus_word(const char* str) { char ch; while ( (ch=*str++) ) { if ((ch<'А')||(ch>'я')) { return 0; } } return 1; } //============================================================================= int main(void) { const char buratino[] = "Буратино"; is_rus_word(buratino); return (0); } avr-gcc -c -mmcu=atmega64 -I. -gdwarf-2 -DF_CPU=14745600UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes.... Код 00003a2a <is_rus_word>: 3a2a: fc 01 movw r30, r24 3a2c: 04 c0 rjmp .+8 3a2e: 80 3c cpi r24, 0xC0 3a30: 10 f4 brcc .+4 3a32: 80 e0 ldi r24, 0x00 3a34: 08 95 ret 3a36: 81 91 ld r24, Z+ 3a38: 88 23 and r24, r24 3a3a: c9 f7 brne .-14 3a3c: 81 e0 ldi r24, 0x01 3a3e: 08 95 ret
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 25 2008, 16:49
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(demiurg_spb @ Dec 25 2008, 19:38)  avr-gcc -c -mmcu=atmega64 -I. -gdwarf-2 -DF_CPU=14745600UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes.... И указание -funsigned-сhar компилятору теперь назывется Цитата Мне вообще всё равно что за тип char (со знаком или без) и всем остальным это должно быть тоже безразлично. Если "безразлично" то поставьте уж signed  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 25 2008, 16:50
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(zltigo @ Dec 25 2008, 17:31)  И за то, что Вы написали, надо больно шлепать, если это перенести не на восьмибитовик  . Исправитесь? Нет я пишу для AVR всегда только так  Ну для x86 естественно использую родной int. avr-gcc -c -mmcu=atmega64 -I. -gdwarf-2 -DF_CPU=14745600UL -Os -fsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes.... Код 3a2a: fc 01 movw r30, r24 3a2c: 05 c0 rjmp .+10 3a2e: 80 5c subi r24, 0xC0; 192 3a30: 80 34 cpi r24, 0x40; 64 3a32: 10 f0 brcs .+4 3a34: 80 e0 ldi r24, 0x00 3a36: 08 95 ret 3a38: 81 91 ld r24, Z+ 3a3a: 88 23 and r24, r24 3a3c: c1 f7 brne .-16 3a3e: 81 e0 ldi r24, 0x01 3a40: 08 95 ret Аналогичный результат если ничего не задавать ни fsigned-char ни funsigned-char, т.е. по умолчанию signed... Исправим формулировку: мне уже не всё равно какой тип у char, т.к. через makefile он принудительно выбран как без знака. Генри Форд: "Форд может быть любого цвета если он чёрный" звучит примерно так  Прошу заметить, что даже так программа будет работать правильно!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 25 2008, 17:27
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(zltigo @ Dec 25 2008, 19:54)  Само собой  . Посему подыщите в <stdint.h> более подходящий тип. Хотя  , по личному опыту бывают варианты, посему спокойнее использовать "свой" у меня он bint - "базовый int" не менее чем байт. На что Вы намекаете?  В <stdint.h> я не смог найти ничего более подходящего для AVR чем uint8_t. Для AVR Ваш bint = unsigned char? Или Вы уже совсем их (AVR) не используете по понятным причинам...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 25 2008, 17:34
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(demiurg_spb @ Dec 25 2008, 20:27)  На что Вы намекаете?  В <stdint.h> я не смог найти ничего более подходящего для AVR чем uint8_t. Естественно на uint_least8_t и/или uint_fast8_t при этом речь я вел о подходящем вообще для портирования кода, а не подходящим только к AVR Цитата Для AVR Ваш bint = unsigned char? Да для всех восьмибитоваков unsigned char. Для все остальных int Цитата Или Вы уже совсем их (AVR) не используете по понятным причинам... Использую  иначе у меня просто не было-бы bint за полной его ненадобностью на 16/32/64 платформах.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Dec 25 2008, 17:43
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(zltigo @ Dec 25 2008, 20:34)  Естественно на uint_least8_t и/или uint_fast8_t при этом речь я вел о подходящем вообще для портирования кода, а не подходящим только к AVR Спасибо! Но хочется всё-таки узнать, когда же есть хоть малейший вред в случае char со знаком. Я так и не смог выдумать такого... И мне что-то подсказывает, что это таки надуманная проблема...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Dec 26 2008, 10:36
|

Местный
  
Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091

|
Цитата(Сергей Борщ @ Dec 25 2008, 17:05)  И должны понимать, что компилятор не может только по значению обычного указателя понимать, какую команду использовать. Иными словами, функции strlen(), memcmp() не могут работать и со строками в ОЗУ и со строками во флеше. Во времена MCS-51, тоже имеющего много разных адресных пространств, компиляторы использовали "универсальные" трехбайтные указатели, в которых первый байт был селектором адресного пространства. Соответственно, и функции, принимавшие такие указатели, вполне успешно работали со строками хоть в памяти данных, хоть в памяти программ. И как раз для начинающих это понятно и удобно, ибо соответствует правилам языка. Продвинутые кодеры могли использовать нестандартные спецификаторы, если тредовалось уменьшить оверхед и/или размер указателей...
--------------------
Всего наилучшего, Alex Mogilnikov
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|