Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Доброго времени суток. Написал простой цикл типа "бегущий светодиод". Сперва одним вариантом, потом другим.

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

	while(1)
	{

		PORTE.OUT = ~led;
		_delay_ms(BLINK_DELAY_MS);
		led <<= 1;
		if (led == 0) led=0b00000001;
	}

	while(1)
	{
		for	(led = 0b00000001;led != 0;led <<= 1)
		{
			PORTE.OUT = ~led;
			_delay_ms(BLINK_DELAY_MS);
		}
	}
Оба работают одинаково :))) Где (в какой литературе) можно почитать, когда какие типы циклов использовать предпочтительнее ? И вообще про хорошие манеры кода на Си.
Просто нашел еще, что можно вообще написать конструкцию типа if (!(led <<= 1)) led=0b00000001; и оно блин работает... Только вот понять такую конструкцию, мой неокрепший мозг пока еще не готов. И поэтому собственно интересует, надо ли к таким конструкциям привыкать (тренировать мозги), или надо наоборот, раскидывать операторы построчно ?
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Эта конструкция - ровно те же две последние строки первого варианта
Контактная информация:
Реклама
Потрогал лапой паяльник
Сообщения: 359
Зарегистрирован: Чт авг 08, 2013 01:06:54

Сообщение Пока_без_кота »

Я понимаю. Я хочу знать, "правильно" ли так писать, или надо (желательно, принято и т.п) расписывать в 2 строки.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Если вам это понятно и вы не пишете руководство для новичков, то вполне нормально. Я и сам вечно начинающий в Си (и не только), но обычно объединяю подобные выражения (что-то вроде if (!(--cnt)) cnt = N).

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

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

Сообщение ARV »

Zhuk72 писал(а):Я и сам вечно начинающий в Си
и я :)
Пока_без_кота писал(а):Я хочу знать, "правильно" ли так писать, или надо (желательно, принято и т.п) расписывать в 2 строки
Моё мнение - чем проще, тем лучше. иногда принцип чуть меняется: чем ближе к сути происходящего, тем лучше.
но если хорошо подумать, оба варианта есть одно и то же.

бритва Оккама не подводит :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Наверное люди делятся на две категории: одни понимают указатели, другие нет :))

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

Имеется функция вывода текста на графический дисплей, к которому прилагается двухмерный массив констант размерностью 159*5 байт, содержащий символы:

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

const unsigned char  lcd_font[159][5] =
{ 
   0x00, 0x00, 0x00, 0x00, 0x00,  // sp - 0
	0x00, 0x00, 0x2f, 0x00, 0x00,  // ! - 1
	0x00, 0x07, 0x00, 0x07, 0x00,  // " - 2
	0x14, 0x7f, 0x14, 0x7f, 0x14,  // # - 3
	0x24, 0x2a, 0x7f, 0x2a, 0x12,  // $ - 4
и т.д.
}
Функция выглядит так:

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

void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
  unsigned char ch, i;
  unsigned char *ptr;
  
  lcd_setxy(row,col*6);
  ptr = lcd_font;            // a value of type "const unsigned char (*)[5]" cannot be assigned to an entity of type "unsigned char *"
  while (*text != "\0")    // operand types are incompatible ("unsigned char" and "char *")
  {
    ch = *text;
    if ((ch >= 32) && (ch <= '~')) ch -= 32;
        else ch = 255;
    for (i = 0; i < 5 ; i++)
    {
      lcd_send(*(ptr+ch * 5 + i),DTA);
    }
    lcd_send(0,DTA);  // Additional space
    text++;
  }
}
Вызываю функцию так:

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

  lcd_out(1,3,"test\0");
Что я делаю неправильно?
Ошибки указаны выше, плюс есть еще предупреждение, касающееся вызова функции. Его я скопировать не могу, оно в виде подсказки вылезает, но говорится там о конвертации между указателем и целым с изменением знака :shock:
Каждый имеет право на свое личное ошибочное мнение.

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

Сообщение ARV »

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

Кстати, "test\0" - ноль в конце лишний, текст в двойных кавычках всегда автоматически дополняется нулем.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Сейчас убегаю, дома постараюсь переварить.
Но я ведь именно массив хочу передать, чтобы он посимвольно вывел его на дисплей.

Про "\0" я в курсе, я это уже в добавил на всякий случай, мало ли что. Вдруг этот радикальный Кайл и это за ошибку считает.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Первая ошибка связана с тем, что вы пытаетесь присвоить неконстантному указателю значение константного. Это "по закону" запрещено, ибо таким образом появляется "дырка", позволяющая изменить константные данные.
А зачем Вам вообще нужен указатель ptr ?
Про вторую ошибку уже сказали - виноваты двойные кавычки. Символ обрамляется в одинарные.
Ну а проще написать так :

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

  while (*text)
  {
Этого будет достаточно.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Спасибо за подсказки.
Сделал так (точнее вернул на место)

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

  lcd_send(lcd_font[ch][i],DTA);
, но все-таки хотелось бы понять почему нельзя через указатель сделать то же самое.
Вычитал тут, правда по плюсам, что может быть const int *ptr и int *const ptr. Оба определения у меня проходят, но ptr = lcd_font все равно вызывает ошибку.
Да и ворнинг на вызове функции остался:
passing 'char [5]' to parameter of type 'unsigned char *' converts between pointers to integer types with different sign
, хотя все скомпилировалось.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Zhuk72 писал(а):Вычитал тут, правда по плюсам, что может быть const int *ptr и int *const ptr.
Один - указатель на константу int, другой - указатель-константа на int.
Т.е. , в одном случае нельзя менять данные по указателю, в другом - нельзя менять сам указатель, но данные по нему можно.
Если будет const int* const ptr, то это будет указатель-константа на константные данные. Т.б. нельзя будет изменять ни указатель, ни данные по нему.
Всё, что находится до символа "*", относится к данным, на которые указывает указатель. Всё, что после символа - к самому указателю.
Zhuk72 писал(а):но ptr = lcd_font все равно вызывает ошибку.
ptr должен быть указателем на такой же тип, с такими же квалификаторами, как и lcd_font.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Массив-то двумерный, а указатель - на одномерный.
Кстати, странно, что на саму инициализацию массива не ругается.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

WiseLord писал(а):Кстати, странно, что на саму инициализацию массива не ругается.
Видимо, понял задумку программиста и сам разделил по блокам из 5-ти байт :)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

[uquote="Аlex",url="/forum/viewtopic.php?p=3126024#p3126024"]ptr должен быть указателем на такой же тип, с такими же квалификаторами, как и lcd_font.[/uquote]
Так и есть. Выше я просто для примера int писал. У себя я написал

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

const unsigned char *ptr;

void lcd_out (unsigned char row, unsigned char col, unsigned char *text)
{
  ptr = lcd_font;
......
}
Массив тоже unsigned char, как и указатель, но тем не менее компилятор ругается: a value of type "const unsigned char (*)[5]" cannot be assigned to an entity of type "unsigned char *"
WiseLord писал(а):Массив-то двумерный, а указатель - на одномерный.
Кстати, странно, что на саму инициализацию массива не ругается.
В источнике этих символов массив представлялся как {{5 байт},{5 байт},{5 байт}, и т.д.}, я по какой-то причине (это было несколько месяцев назад) внутренние {} убрал. Получился одномерный массив, но адресуемый как двухмерный. Я, кстати, такое и раньше делал, ошибок в работе это не вызывало.
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Zhuk72 писал(а):Массив тоже unsigned char, как и указатель, но тем не менее компилятор ругается: a value of type "const unsigned char (*)[5]" cannot be assigned to an entity of type "unsigned char *"
А, ну так правильно. Массив то двумерный.
Вот так надо :

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

ptr = lcd_font[0];
если указываем на одну строку.
Или так :

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

ptr = &lcd_font[0][0];
если хотим указать на конкретную ячейку.

Добавлено after 6 minutes 42 seconds:
Т.е., в данном случае, мы можем сделать так :

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

    ptr = lcd_font[ch];
    for (i = 0; i < 5 ; i++)
    {
      lcd_send(*(ptr + i), DTA);  // или lcd_send(ptr[i]), DTA);
    }
или так :

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

    for (i = 0; i < 5 ; i++)
    {
      ptr = &lcd_font[ch][i];
      lcd_send(*ptr,DTA);
    }
Но это будет равносильно этому :

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

lcd_send(lcd_font[ch][i],DTA);
где ptr получается лишним.
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Спасибо большое, ptr = lcd_font[0]; подошло.
Я так пробовал и раньше, но тогда, видать, мешала ошибка, связанная с константой.
Завтра с отсылкой еще буду разбираться, а пока у меня что-то функция дилей не работает. Собрал все на макетке, прогнал дебаггером, оказалось,что дисплей инициализацию не проходит из-за зацикленной задержки. Что-то я там с SysTick'ом не то сварганил :)
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Открыл глаза
Сообщения: 76
Зарегистрирован: Вс июн 18, 2017 08:12:41

Сообщение Зурбаган »

[uquote="Zhuk72",url="/forum/viewtopic.php?p=3126084#p3126084"]ов массив представлялся как {{5 байт},{5 байт},{5 байт}, и т.д.}, ... внутренние {} убрал. Получился одномерный массив, но адресуемый как двухмерный. Я, кстати, такое и раньше делал, ошибок в работе это не вызывало.[/uquote]
В принципе, размерность массива явно указывается при его объявлении количеством скобок []. Внутри него вы можете получать доступ к элементам как угодно, но его размерность от этого не изменится. В регистрах памяти массив, независимо от его размерности, будет располагаться линейно, элемент за элементом, строка за строкой.
В двухмерном массиве array[][] при его инициализации строки можно разделять внутренними скобками {{ , , },{ , , },{ , , },{ , , }}. В одномерном массиве такая запись приведет (может привести) к предупреждению "скобки вокруг скалярной инициализации".

[uquote="Zhuk72",url="/forum/viewtopic.php?p=3125816#p3125816"]Наверное люди делятся на две категории: одни понимают указатели, другие нет :))[/uquote]
Эт веееерно :) Вообще-то, тут по большей части теоретический вопрос. В умных книшшках много раз описывались указатели, но мало прочесть, надо опробовать самому на деле. И автору (Zhuk72) желательно было бы потренироваться "на кошках", т.е. на простом абстрактном примере, а не влезать сразу к шрифтам и дисплею.
Указатель подобен курсору в текстовом редакторе, или прямоугольной рамке размером в один символ (равносильно char *ptr), и эта рамка может перемещаться по строке текста. Позиция указателя будет отсчитываться от начала строки (т.е. значение переменной ptr, хранящей некоторый адрес из адресного пространства). Рамку можем перемещать в любую позицию. Например, перемещаем на первую букву в выбранном слове ( char *ptr = word1 ) и в рамке видим эту букву. Рамку можем двигать на какое-то число позиций вправо или влево по слову ( ptr += 5; ptr--) и наблюдать в рамке буквы ( a = *ptr ). Номер позиции рамки от начала всей строки мы записываем в свободное место той же строки (переменная ptr сама находится в том же адресном пространтве), а так же в свободном месте строки можем записывать буквы, которые видим в рамке ( переменная, в которую читается по указателю, тоже находится в том же адресном пространстве). Причем, мы можем перескочить за границы интересующего нас слова или вообще попасть туда, где нет текста, но есть место под буквы (перемещаясь по массиву, мы можем запросто выйти за его границы и ошибок компиляции не будет). Причем, буквы могут быть разной ширины, и чтобы увидеть в рамке именно то, что интересует, нужно выбирать рамку строго по ширине конкретной буквы (т.е. указатель и переменная должны быть одного типа (кол-ва байт)). К тому же, буквы могут не быть в составе осмысленных слов (указатели могут указывать на отдельные переменные).

Изображение

Просто так взяв рамку и бросив ее на текст, мы можем попасть на любую букву. Это к слову об использовании неинициализованных указателей, которые могут указывать на любое случайное место. Поэтому, взяв рамку в руки, обязательно определим, какое место в строке нас интересует. То есть, объявив указатель, скажите ему, на что он указывает. В крайнем случае, напишите char *pa = (void*)0, сделав его "нулевым указателем". (чисто технически он указывает на адрес 0 в адресном пространстве). Вместо 0 вы можете записать любой другой адрес, либо получить адрес какой-то переменно с помощью символа &.

Встречается ситуация, когда указатель может указывать на переменную не своего типа. Тогда выдается предупреждение о несовместимости типов переменной и указателя на нее. Образно выражаясь, ширина рамки не совпадает с шириной символа. И если это сделано сознательно, а не в результате ошибки, то можно выполнить приведение типа (подогнать ширину рамки вручную по месту). Вот в таком примере мы сможем четырехбайтную переменную var разложить на отдельные байты в отдельных переменных byte3 - byte0. (обратная последовательность связана с тем, что младший байт имеет больший адрес, чем старший)

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

 int var = 0x12345678;
 char *ptr = (char*)&var;    // указатель будет указывать только на 1 байт переменной var

  byte3 = *ptr++;   // чтение переменной по указателю и последующий инкремент указателя, передвигая его на следующий байт
  byte2 = *ptr++;
  byte1 = *ptr++;
  byte0 = *ptr;
Используя возможности приведения типа, можно создать указатель на void, то есть указатель на неопределенный тип переменной, и использовать этот указатель как универсальный, для указания на любой тип. Объясняется это просто - тип void имеет размер в 1 байт (по соглашению в новых редакциях языка)

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

  void *pv = (void*)0;    // "нулевой" указатель на void

  int a = 0x12345, x;
  char b = 'A', y;

  pv = &a;              // получает адрес переменной любого типа
  x = *((int*)pv);    // чтение по указателю с приведением указателя к типу читаемой переменной. x = 0x12345

  pv = &b;
  y = *((char*)pv);  // y = 'A'
      /* можно пойти еще дальше и объявить указатель непосредственно на char, который будет выражаться через указатель на void с приведением типа */
  char *pc;
  pc = (char*)pv;
     /* и теперь использовать уже его */
  char symb;
  symb = *pc; // фактически, symb = b непосредственно
  *pc = 'B';  // фактически, b = 'B' непосредственно
без приведения типа указателя компилятор будет выдавать предупреждение о несовместимости типов. А void* - это в большей мере условность, наглядно показывающая универсальный указатель. Этот механизм используется для передачи через параметры функции данных произвольного размера, в том числе и структуры. Параметр функции используется как "универсальный передатчик". Метод используется во FreeRTOS при передаче произвольных параметров в создаваемую задачу.

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

------
Что касается доступа к элементам двухмерного массива через индексацию и через указатели, тут вот какая штука.
Допустим, у нас есть двухмерный массив
array[3][5] = {{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14}}; с одинаковой длиной строк:

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

 0   1   2   3   4
 5   6   7   8   9
10  11  12  13  14
Доступ к произвольному элементу при помощи индексации осуществляется по типу X-Y (не забываем, что индексация происходит с 0, как по горизонтали, так и по вертикали!)

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

  char a;
  int x, y;
  x = 2;
  y = 1;
  a = array[y][x];
  a = array[y+1][x-2]; 
таким способом удобно получать доступ к произвольному элементу по его координатам.
А вот доступ по порядковому номеру (по смещению от начала) удобнее выполняется через указатель.

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

  char *ptr = &array[0][0];	// создается указатель на элементы массива и ему сразу присваивается адрес начала массива
  ptr += 8;	// смещение указателя на 8 позиций от начала массива
  a = *ptr;	// получение элемента 8-го массива
  ptr++;	// указатель перемещается на следующий элемент массива
  a = *ptr;	// получение следующего элемента массива
  ptr -= 3; // указатель перемещается на 3 позиции назад от текущей
  a = *ptr;
  a = *ptr++; // получение текущего элемента с последующим смещением указателя на след.элемент
  ptr += (1 * 5); // перемещение указателя на следующую строку ниже. 1 - число строк вниз, 5 - ширина массива (X)
  a = *ptr; // получение элемента строкой ниже (12-й)
однако, как видим, произвольный доступ по координатам X-Y через указатель записывается гораздо хуже, потому что нужно знать именно ширину строки, т.е. количество элементов в строке.
Таким образом, указатели хорошо подходят для последовательного считывания в одномерном или двухмерном массиве. Но указатели усложняют жизнь, когда нужно прочитать некоторую ограниченную область в двухмерном массиве, либо при произвольном доступе в координатах X-Y.
С таким простым шрифтом, как у Zhuk72, можно работать хоть как - по указателю или по индексации, разницы большой нет.
Ёшкин кот обормот
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1231
Зарегистрирован: Ср янв 29, 2014 08:41:31
Откуда: Баку

Сообщение Zhuk72 »

Спасибо большое за такую серьезную работу, это действительно впечатляет!
По указателям я несколько раз читал КиР, смотрел одно обширное видео на ютубе, потому смысл сего чуда представляю.
Но вот когда доходит до практической реализации, у меня в особо сложных случаях шарики за ролики заходят.

Почитаю ваше объяснение, может просветлею в этот раз :D
Каждый имеет право на свое личное ошибочное мнение.

У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Контактная информация:
Открыл глаза
Сообщения: 76
Зарегистрирован: Вс июн 18, 2017 08:12:41

Сообщение Зурбаган »

Да нет, тут не в практической реализации дело. Судя по вашему первому вопросу, уж извините, дело в теоретических пробелах.
Если в описании функции в параметрах запрашивается указатель, то при вызове функции должен быть передан адрес какой-либо переменной. Почему-то никто явно этого не заметил, а написали, что "ошибка не в указателях" и дальше пошли в какие-то далекие дебри про двухмерные указатели, только лишь мельком зацепившись за несоответствие параметра функции.
А раз так, то разберем детально:

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

void lcd_out (unsigned char *text)   // параметр функции в виде указателя
{
   unsigned char ch;     // переменная, в которую будет читаться то, что принято по указателю
   ch = *text;         // собственно, это и есть чтение в переменную по принятому указателю
}

void main(void)
{
  unsigned char symbol = 'A';    // переменная с одиночным символом
  unsigned char message[] = "whattafaka";    // массив переменных в виде строки, инициализированной последовательностю символов
  lcd_out(&symbol);     // вызов функции и передача в нее параметра в виде адреса одиночной переменной

  lcd_out(message);    // вызов функции и передача в нее параметра в виде адреса массива символов.
                       // Без знака &, поскольку имя одномерного массива - это и есть его адрес, 
                      //адрес первого его элемента
}
Для той функции, которая была изначально задана, будет работать именно приведенный вариант вызова.
А вот попытка сделать вызов вот так (как поначалу начали советовать):

lcd_out('A');
приведет к предупреждению (если оно включено в настройках) о несовместимости типов. Можно плюнуть на это, а можно прикинуться "типа умным" и вручную привести к запрашиваемому функцией типу указателя, используя наработки из ранее написанного мною.

lcd_out((unsigned char*)'A');
Предупреждений нету, но функция делает совсем не то, что ожидалось. А теперь вспомним, что запрашивает параметр? Он запрашивает какой-то адрес. А что есть 'A' ? Это ANSI-представление числа 0х41. То есть, мы явным образом передаем адрес памяти 0х41. Для функции это будет указатель (ссылка) на адрес 0х41. При дальнейшей работе функции идет чтение по принятому в параметре адресу 0х41. Что там физически находится - хрен его знает. Да, работает. Но результат не тот, что ожидался.

Но чтобы раз и навсегда разобраться с вариантами, теперь перепишем немного нашу функцию и попробуем вызвать ее так, как было в вашем первом вопросе:

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

void lcd_out (const char *text)
{
	char ch;
	ch = *text;
}

/---
void main(void)
{
    lcd_out("Whattafaka");  // строка символов в качестве параметра
}
И у нас уже замечательнейше работает и выдает то, что и ожидали (однако, предыдущий вариант с адресом массива уже работать не будет).
Именно на этом построены всякие printf, в том числе и самописные.
Так вот видите, где собака зарыта то? А вы говорите "не в указателях дело", да "кавычки не те". В них дело, в них самых. :)

Кстати, можно не извращаться, а для такого случая использовать готовую встроенную sprintf или ее облегченный вариант siprintf из набора tiny_printf. Но об этом - позже.
Ёшкин кот обормот
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18787
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»