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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Аlex писал(а):Предположим, какой-нибудь новичок воспользуется Вашим примером и создаст какую-нибудь функцию, возвращающую чего-нибудь. Возьмём, для примера, возвращение даты ну или время, в строке.
....
А потом, не понимая всех прелестей Вашего финта, будет её использовать:
...
и начнёт, к примеру, их сравнивать, думая, что в этих строках разное содержимое.
То всё, что мне останется сказать, это прочесть ещё раз комментарий к коду, начинающийся со слов «так не выйдет»:
avreal писал(а):

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

char *ftos(float val)
{
    static char buf[20];
    // преобразовываем
    return buf;
}  
Но такую функцию нельзя дважды в один printf вставить:

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

    printf("Val = %s +- %s\n", ftos(average), ftos(rms)); // Так не выйдет! Буфер-то один      
Вы, похоже, тоже не обратили внимания, что я написал «Так не выйдет! Буфер-то один»
Аlex писал(а):Наверное, всё-таки, будет правильнее и нагляднее видеть подобный код(?):
void Get_Time(char* pStr){
Наверное, всё таки, участник форума спросил, как ему написать функцию char *ftos(float). Я указал одновремённо и вариант исполнения функции, и его недостаток. Если Вы или другой новичок, которому «пофиг на стандарты» и хочется пользоваться языком без понимания происходящего, этого комментария не заметили -- не виноват ни я, ни язык С.
Аlex писал(а):PS: И ещё, в догонку, новичкам пофиг на Ваши стандарты и указатели. Они понимают так, как им проще.
...
И моему участку мозга, отвечающему за логику, так-же как и многим, пофигу на эти Ваши стандарты, которыми Вы прикрываетесь и через каждое слово вставляете. :)
Чем быстрее новички поймут, что нужно уходить с уровня бабки на лавочке «а тут по радио передавали, что sizeof(array) возвращает размер массива, хотя слово array это указатель на первый элемент, так я попробовала, в моей плите то же самое! Работает! это ж надо!» и разобраться во внутренностях языка, тем быстрее перестанут быть новичками.
Вы же своё нежелание понять язык С прикрываете фразой про то, что Ваш учасок мозга, отвечающий за логику, считает логичным пользоваться инструментом без понимания его работы. Ну ладно — лень читать стандарт самому. Но я же бесплатно и с пояснениями его читаю вслух. Но даже это вызывает неприятие.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

illarionovsp писал(а):Коты, дорогие. Расскажите мне, бестолковцу, почему такая функция:
void mf(char* s) { s="15"; }
ничего не делает. С чем в s вошёл, с тем и вышел. А такая:
void mf(char* s) { itoa(15, s}; }
возвращает в s строку 15, не важно, с чем вошёл.
В первом случае локальной переменной s, проинициализированной при вызове функции адресом какого-то массива, Вы присваиваете новое значение, указывающее на строку. В первую функцию mf() не передался Ваш буфер, туда передался адрес его первого элемента. Изменение в локальной переменной этого адреса ничего не меняет.
Есть такая терминология «передача по значению»/«передача по имени». Передача указателя по сути есть формой «передачи по имени». Изменение этого имени ничего не меняет в исходной переменной.
Точно такой же эффект будет при

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

void mf(char* s) {
    char bbb[] = "15";
    s=bbb;
}
Поскольку к буферу, на котрый указывал s, обращений не было, его содержимое и не поменялось.
Поменяется только при «разыменовании» (dereference), например, так

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

void mf(char* s) {
    *s     = '1';  // Это все допустимые обращения по указателю.
    s[1]   = '5';
    *(s+2) = '\0';
}
Или так, меняя у себя копию адреса

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

void mf(char* s) {
    *s++ = '1';
    *s++ = '5';
    *s   = '\0';
}
Или так

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

void mf(char* s) {
    strcpy(s, "15");
}
Тут мы передаём значение s (адрес буфера, в который нужно записать данные) и указатель на неименованный массив из трёх char-ов "15" в другую функцию, которая копирует данные, записывая их по адресу, полученному по цепочке в s.
Аналогичный процесс в варианте с itoa, которая в своём аргументе принимает копию адреса исходного буфера и обращается по нему, меняя всё тот же массив, который лежит на месте и ждет, пока его адрес гуляет по функциям.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина

Сообщение Tolmi »

illarionovsp писал(а):Коты, дорогие. Расскажите мне, бестолковцу, почему такая функция:

void mf(char* s) { s="15"; }
ничего не делает. С чем в s вошёл, с тем и вышел. А такая:
Мы передали внутрь функции указатель, адрес чего-то. Внутри функции эту переменную,указатель изменили, но то, на что он раньше ссылался, осталось абсолютно неизменным. По окончанию работы функции эта переменная благополучно потерялась, и вне функции ничего не произошло.
void mf(char* s) { itoa(15, s}; }
возвращает в s строку 15, не важно, с чем вошёл.
Правильно, потому что itoa возвращает в буфер, который ей передали, строку.
Да, и особой пикантности в этой ситуации добавляют неинициализированные указатели :) Я в конце 80-х преподавал C, у тогдашних слушателей были те же проблемы и вопросы :)
И ещё вопрос, риторический, конец этому будет, или как?
1. Практика, практика, и ещё раз практика.
2. Начинать работу с ассемблера, чтобы понять, как работают остальные языки программирования ;)
3. Может оказаться, что программирование - это просто не твоё, есть и такие люди, в этом нет ничего обидного. Мне вот не стать балериной.
ЗЫ. Ничего не делает и в VC++ 2008.
Потому что это поведение штатно и прогнозируемо для языка, а не компилятора.
Но бездумное применение монстроподобных конструкций перетянутых с "большого серого брата IBM" на МК приводят к плачевному раздутию кода и тормознутости...
И откуда там возьмется монстрообразность и тормознутость? Код можно даже в уме прикинуть, какой получится. Ничего необычного.


UPD:
Вы же своё нежелание понять язык С прикрываете фразой про то, что Ваш учасок мозга, отвечающий за логику, считает логичным пользоваться инструментом без понимания его работы. Ну ладно — лень читать стандарт самому. Но я же бесплатно и с пояснениями его читаю вслух. Но даже это вызывает неприятие.
:beer: :beer: :beer:
In theory, theory and practice are the same. In practice, they're not.
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Tolmi писал(а):Потому что это поведение штатно и прогнозируемо для языка, а не компилятора.
Во! Вот именно это я каждый раз цитатой из стандарта хочу сказать. И про «языка», и про прогнозируемость. Никакого шаманства и тайного знания.
Прикрывать мне нечего (ну кроме того, что есть у каждого уважающего себя кота, но то не стандартом прикрывают).
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Реклама
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Кислый писал(а):черт. есть ли какая-нибудь возможность проверить скомпиленный бинарник на множественные включения заголовков ?
Что имеется ввиду под множественными включениями?
Несколько раз один и тот же файл? Разные файлы, но пытающиеся (пере)определить одни и те же вещи?
Так если конфликтов не было, то какая разница, сколько раз включено (если там не задаются житрім образом массивы со сгенерированными именами). А если конфликты были, то компилятор ругнётся и не создаст бинарник.

И что имеется ввиду под бинарником.
В принципе, в объектном или исполняемом файле, для встроенных систем -- в файле системы, аналогичном elf для gcc, при включенной при компиляции генерации отладочной информации можно как-то выкровырять информацию о том, какой инструкции соответствует (приблизительно :-) ) какая строка какого файла исходников. Но можно ли из этого получить искомое -- не знаю.

А что за задача стоит?
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

просто я пишу через жопу, мой товарищ пишет через жопу. я не лезу в его код, он в мой.. а проэкт один, используемые инклуды тоже
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Так а что в данном случае за беда с множественными включениями?
В смысле стандартная штука

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

#ifndef NAME_OF_THIS_FILE_H
#define NAME_OF_THIS_FILE_H

// А пофиг, сколько раз меня includ-нули, я один раз отработаю

#endif // NAME_OF_THIS_FILE_H
уже есть, но не помогает?
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Прорезались зубы
Сообщения: 234
Зарегистрирован: Ср апр 29, 2009 22:22:13
Откуда: СПб

Сообщение illarionovsp »

Коты, дорогие, спасибо. Критику принимаю отчасти.
Про указатели читал, знаю, но почему-то считал, что char* s - это и есть указатель. Поэтому s="15", это и есть указатель на строку, в которой '1', '5' и конец строки.
Стал быть ошибался.
Только
char* mf(void) {
static char sf[10]; strcpy(sf, "15"); return sf; } // функция
и
char sm[10]; sm=mf(); // вызов из главной
не идёт.
Для чистоты эксперимента пробовал на DevC++.
Я с ним когда-то работал. Потом подсел на VC++.
На ассемблере программировать не буду. Задача у меня генератор, надо кнопки опрашивать, дисплеем управлять да блютуз к делу приспособить
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

illarionovsp писал(а):Про указатели читал, знаю, но почему-то считал, что char* s - это и есть указатель.
Поэтому s="15", это и есть указатель на строку, в которой '1', '5' и конец строки.
Стал быть ошибался.
Не ошибался. Это и есть указатель. Но не сама строка. Скопировать указатель не означает скопировать строку, присвоить указатель не означает присвоить строку.
illarionovsp писал(а):char* mf(void) {
static char sf[10]; strcpy(sf, "15"); return sf;
} // функция
и
char sm[10]; sm=mf(); // вызов из главной
не идёт.
Во, «дайте больше кода» вот ради этого и говорилось всё время:

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

char sm[10]; sm=mf(); // вызов из главной
Тут sm -- массив символов. mf возвращает указатель на первый элемент другого массива. Одно другоме присвоить нельзя.

С mf можно поступать так:
присвоить другому указателю и тот указатель где-то использовать

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

    char *pc = mf();
    puts(pc); 
Напрямую использовать mf() там, где ожидается указатель на char как указатель на строку символов

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

    // скопировать строку из одного массива в другой
    char sm[20];
    strcpy(sm, mf()); // только не забывать, что всё должно влазить   
Но в таком случае действительно лучше передать в mf() массив mf(sm) и пусть она заполняет.

Сразу отдать на печать

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

    printf("Result = %s\n", mf()); 
вот ради таких мест, где нужен именно указатель на строку символов, функция в таком виде нужна и удобна.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Говорящий с текстолитом
Сообщения: 1658
Зарегистрирован: Вс дек 11, 2011 05:25:04
Откуда: Киев, Украина

Сообщение Tolmi »

illarionovsp писал(а): char* mf(void) {
static char sf[10]; strcpy(sf, "15"); return sf; } // функция
и
char sm[10]; sm=mf(); // вызов из главной
не идёт.
:facepalm:

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

char * mf(void){static char sf[10]; strcpy(sf,"15");return sf;}
///
char *sm; sm=mf(); // где-то так должно выглядеть :)
Но всё же советую книжки внимательно почитать, хотя бы Кернигана.


PS И да, в +10500 раз : В C НЕТ ОПЕРАЦИЙ ПРИСВАИВАНИЯ ДЛЯ ТИПОВ "МАССИВ СИМВОЛОВ"!
Это вам не бэйсик!
In theory, theory and practice are the same. In practice, they're not.
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар

Сообщение Кислый »

avreal писал(а):уже есть, но не помогает?
походу мингв глючит. на новой системе все норм, спасибо
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Tolmi писал(а):PS И да, в +10500 раз : В C НЕТ ОПЕРАЦИЙ ПРИСВАИВАНИЯ ДЛЯ ТИПОВ "МАССИВ СИМВОЛОВ"!
«массив чего угодно».

p.s. «для знатоков штучка» © Жванецкий:
Осторожно, жёсткий С! Использован термин из стандарта! Никаких эвфемизмов!
СпойлерНо если завернуть массив в структуру... Но всё равно строковый литерал так не присвоить.
Но если использовать compound literal из стандарта C99... То можно и строковый литерал, и еще и в компании с чем-нибудь.

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

#include <stdio.h>

typedef struct {
        int value;
        char descriptor[10];
} strarr_t;

strarr_t a;

int main()
{
        a = (strarr_t){10, "kwa"};
        printf("%s is %d\n", a.descriptor, a.value);
}
 
Последний раз редактировалось avreal Ср окт 17, 2012 22:35:38, всего редактировалось 1 раз.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

illarionovsp писал(а):char* mf(void) {
static char sf[10]; strcpy(sf, "15"); return sf; } // функция
и
char sm[10]; sm=mf(); // вызов из главной
Ну вот, не прошло и полгода, и начались сбываться мои предсказания :)) Зато всё по стандарту :)))
Запудрили мозги человеку своими "стандартными" возвратами. Буквоеды, мля :facepalm:
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Аlex писал(а):Ну вот, не прошло и полгода, и начались сбываться мои предсказания :)) Зато всё по стандарту :)))
Запудрили мозги человеку своими "стандартными" возвратами. Буквоеды, мля :facepalm:
Человек совершил ту же ошибку, которую он без никаких возвратов совершил бы с

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

    char a[10];
    char b[10];
    a = b;
Или с

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

char a[10];

void foo()
{
    a = "15";
}
Так что проблема не в пугающих Вас «стандартных возвратах», а в непонимании различия массивов и указателей, которая вылезет в куче мест и без этого.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

Человек совершил ошибку, подумав, что функция возвратит строку, с которой он сможет что-либо сделать. По этому подобное я и назвал "финтом", догадываясь, что "быть беде"...
И уж поверьте мне, меня давно уже не пугают подобные "стандартные возвраты". Это Ваше заблуждение. Так-же, как и то, что я пользуюсь языком без понимания происходящего.
Впрочем, я уже всё сказал несколькими постами выше. Не смею больше Вас отвлекать от обучения. С удовольствием послежу за вашей дискуссией со стороны, если позволите...
Опытный кот
Аватара пользователя
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна

Сообщение avreal »

Аlex писал(а):Человек совершил ошибку, подумав, что функция возвратит строку, с которой он сможет что-либо сделать. По этому подобное я и назвал "финтом", догадываясь, что "быть беде"...
Укажите мне разницу между foo() и moo(), чтобы я понял, почему данная "бытьбеда" связана именно с возвратом из функции, а не с непониманием массивов и указателей. Отдельно прошу рассмотреть случай inline-подстановки функции sf().

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

char sm[10];

void foo()
{
    sm = "15"; // Ну вот же она, строка! Живая! С ней же можно что-то делать!
               // Никакой не изврат-возврат! Почеемуу ничего не выходииит!
}

const char *sf()
{
    // Если кто-то думает, что есть хоть какая-то разница между этим
    return "15";
    // и этим
    // static const char b[] = "15";
    // return b;
    // то он очень крепко ошибается
}

void moo()
{
    sm = sf(); // А, ну тут понятно, тут предсказанная предсказателем беда из-за возврата такой же строки
} 
Аlex писал(а):Впрочем, я уже всё сказал несколькими постами выше.
Да, да, я понял. Стандарты фигня. Если человек начинающий, то таким ему и остаться с таким подходом.
Аlex писал(а):Не смею больше Вас отвлекать от обучения. С удовольствием послежу за вашей дискуссией со стороны, если позволите...
Да нет уж. Пребывайте в спокойном удалении от стандарта.
Мне уже говорил один (вполне уважаемый на этом форуме человек) что я тут «неформат» со своими попытками что-то объяснить.
Впрочем, он мне это говорил в привате другого форума. Где, такое впечатление, вполне не против был меня почитать.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

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

Укажите мне разницу между foo() и moo()
Вы хотите проверить мои знания что-ли ? Зачем Вам расказывать то, что Вы и так прекрасно знаете.
Если Вы до сих пор не поняли в чём заключается "бытьбеда", то я уже Вам ничем не могу помочь.
Попробуйте перечитать мои посты ещё раз и код человека, которому Вы что-то пытаетесь объяснить. Может быть, по этому коду поймёте где зарыта эта "бытьбеда".
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

Аlex писал(а):Может быть, по этому коду поймёте где зарыта эта "бытьбеда".
Может все дело в непонятных названиях переменных и функций?
Если назвать ту же функцию sf() как нибудь str_to_ptr() может тогда понятно будет, что возвращает то она именно указатель?
Хотя для полного понимания сути происходящего нужно еще и в отношении выражения sm="15" понимать, что sm здесь это всего лишь адрес первой ячейки массива и нельзя самому числу ничего присвоить.

Кстати видел тут недавно вопрос о том, что есть несоответствие типов нужен 'uchar*' , а есть строка "some_str" видать строка то хранится во флешь и компиль пишет о несоответствии с типом 'flash uchar*'
В этом случае выходит нужно воспользоваться функцией похожей на эту

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

uchar* foo(flash uchar* string){
static char sf[10]; strcpy(sf, string); return sf;
 
или есть более разумные варианты?
Контактная информация:
Прорезались зубы
Сообщения: 234
Зарегистрирован: Ср апр 29, 2009 22:22:13
Откуда: СПб

Сообщение illarionovsp »

Ребята-коты, вот хорошо то.
Исправил строго как рекомендовал Tolmi. Работает. Тогда сразу накатал:
printf("s=%s", mf())
Работает на ура!
А почему раньше не работало? static'а не хватало! Во, дяла.
Но главное понимаю, почему раньше не работало, а теперь работает, А говорят, что я совсем с возрастом отупел. Не совсем...
Ответить

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