Jump to content

    

Функция sprintf

Как же тогда делать?
void Reverse(char *str, int len)
{
    int i=0, j=len-1, temp;
    while (i<j)
    {
        temp = str[i];
        str[i] = str[j];
        str[j] = temp;
        i++; j--;
    }
}
int IntToStr(int x, char str[], int d)
{
    int i = 0;
    while (x)
    {
        str[i++] = (x%10) + '0';
        x = x/10;
    }

    // If number of digits required is more, then
    // add 0s at the beginning
    while (i < d)
        str[i++] = '0';

    Reverse(str, i);
    str[i] = '\0';
    return i;
}
// Converts a floating point number to string.
void FtoA(float n, char *res, int afterpoint)
{
    // Extract integer part
    int ipart = (int)n;

    // Extract floating part
    float fpart = n - (float)ipart;

    // convert integer part to string
    int i = IntToStr(ipart, res, 0);

    // check for display option after point
    if (afterpoint != 0)
    {
        if (ipart==0)
            res[i++] = '0';
            
        res[i] = '.';  // add dot

        // Get the value of fraction part upto given no.
        // of points after dot. The third parameter is needed
        // to handle cases like 233.007
        fpart = fpart * pow(10, afterpoint);

        IntToStr((int)fpart, res + i + 1, afterpoint);
    }
}

 

Share this post


Link to post
Share on other sites
а вообще sprintf монструозная функция для эмбедед. никогда не использовал ее.

Поразительно - человек беспокоится о расходе стека printf()-ом, но при этом даже не задумываясь лепит кучу константных данных в ОЗУ (строки, массивы указателей на строки и т.п. - как видно из разных его сообщений на форуме). В местах где это ну совершенно не нужно. :wacko:

Share this post


Link to post
Share on other sites
Поразительно - человек беспокоится о расходе стека printf()-ом, но при этом даже не задумываясь лепит кучу константных данных в ОЗУ (строки, массивы указателей на строки и т.п. - как видно из разных его сообщений на форуме). В местах где это ну совершенно не нужно. :wacko:

 

а что плохого если строки лежат во txt секции?

Share this post


Link to post
Share on other sites
а что плохого если строки лежат во txt секции?

Да если бы они лежали только в .text...

Edited by Arlleex

Share this post


Link to post
Share on other sites
а что плохого если строки лежат во txt секции?

В какой txt-секции? Так как Вы пишете, все Ваши строки и указатели на них лежат в ОЗУ + инициализирующие значения лежат во флешь.

А если передаёте в некую функцию строку типа: Func("си_не_знаю_пишу_как_попало") и эта Func объявлена как Func(char *), то такой вызов говорит компилятору до вызова функции создать переменную char t[] = "си_не_знаю_пишу_как_попало"; где-то в ОЗУ - или на стеке или в static памяти, проинициализировав её в runtime из константы char const ti[] = "си_не_знаю_пишу_как_попало"; во флешь.

Share this post


Link to post
Share on other sites
А если передаёте в некую функцию строку типа: Func("си_не_знаю_пишу_как_попало") и эта Func объявлена как Func(char *), то такой вызов говорит компилятору до вызова функции создать переменную char t[] = "си_не_знаю_пишу_как_попало"; где-то в ОЗУ - или на стеке или в static памяти, проинициализировав её в runtime из константы char const ti[] = "си_не_знаю_пишу_как_попало"; во флешь.

Ну это уже совсем трэш, угар и содомия. Вот не при помню ни одного повода, по которому неявно создавалась бы строка в ОЗУ. И в данном случае точно нет.

Поправка: если возвращать из функции по значению структуру, содержащую строку, эта структура будет временно создана на стеке. Но это совсем другой случай, конечно.

Share this post


Link to post
Share on other sites
Ну это уже совсем трэш, угар и содомия. Вот не при помню ни одного повода, по которому неявно создавалась бы строка в ОЗУ. И в данном случае точно нет.

попробуйте:

char t[] = "строка";

где будет создана t?

Share this post


Link to post
Share on other sites
попробуйте:

char t[] = "строка";

где будет создана t?

Это явно созданная в ОЗУ строка, о чём "char t[]" недвусмысленно говорит. У вас в дивном примере чуть выше написано совсем иначе.

Share this post


Link to post
Share on other sites
Это явно созданная в ОЗУ строка, о чём "char t[]" недвусмысленно говорит. У вас в дивном примере чуть выше написано совсем иначе.

Ну так если аргумент функции описан как char *, то эта функция внутри имеет право выполнять запись по такому указателю. А значит компилятор не должен позволять передавать туда указатели на константные объекты. Разве не так?

Share this post


Link to post
Share on other sites
Ну так если аргумент функции описан как char *, то эта функция внутри имеет право выполнять запись по такому указателю. А значит компилятор не должен позволять передавать туда указатели на константные объекты. Разве не так?

Нет, не так. Явным приведением типа можно отсечь от указателя const, и компилятор не пикнет. Копию в ОЗУ точно не будет создавать.

В порядке ликбеза: объявление переменной и список аргументов функции - это совсем разные штуки. Какое-то совпадение в семантике есть, но есть и кардинальные различия.

Share this post


Link to post
Share on other sites
Нет, не так. Явным приведением типа можно отсечь от указателя const, и компилятор не пикнет.
Это жульничество, от такого компилятор не защищает. Вы напрасно спорите с jcxz, он прав. Более того, gcc уже давно ругается на char * text = "слава мне, победителю драконов";

warning: ISO C++ forbids converting a string constant to ‘char*’

Share this post


Link to post
Share on other sites
Вы напрасно спорите с jcxz, он прав.

Нет, не напрасно. Я спорю вот с этим:

А если передаёте в некую функцию строку типа: Func("си_не_знаю_пишу_как_попало") и эта Func объявлена как Func(char *), то такой вызов говорит компилятору до вызова функции создать переменную char t[] = "си_не_знаю_пишу_как_попало"; где-то в ОЗУ - или на стеке или в static памяти

Это очевидное заблуждение.

Share this post


Link to post
Share on other sites
Это очевидное заблуждение.

Вы правы. У меня в проекте вся менюшка выполнена в стиле lcd.Printx(0, " си_не_знаю_пишу_как_попало ");, где void Printx(uint8_t x,char *s);. Заглядываем в map по модулю меню.

    Module                       ro code  ro data  rw data
    ------                       -------  -------  -------
    Menu.o                         2 436        7       20

 

Share this post


Link to post
Share on other sites
Нет, не так. Явным приведением типа можно отсечь от указателя const, и компилятор не пикнет. Копию в ОЗУ точно не будет создавать.

Ну я вообще-то говорю не про явное приведение типа.

А когда вообще без приведения типа функции, принимающей указатель на переменную, передаётся константа.

Явным приведением типа программист просто говорит, что в данном конкретном случае здесь передаётся "не то что можно ожидать по типу объявленного символического имени, а нечто другое".

Если функция использует принятый указатель только для операций чтения, то при объявлении такой функции надо этому указателю (аргументу) назначать модификатор const. Частный случай - член-функция класса, использующая члены класса только на чтение (и вызывающая только const член-функции класса) - тоже должна объявляться с модификатором const.

Если функция использует принятый аргумент-указатель и для операций записи, то тогда нужно описывать без слова const.

И компилятор, при передаче аргумента такой фукции, будет проверять чтобы const-указатели не передавались в не-const аргументы функций.

 

Вы правы. У меня в проекте вся менюшка выполнена в стиле lcd.Printx(0, " си_не_знаю_пишу_как_попало ");, где void Printx(uint8_t x,char *s);. Заглядываем в map по модулю меню.

Значит Ваш компилятор в этом случае не проверяет соответствие типов передаваемых данных и аргументов функции. И плохо. Это его недостаток.

Но это не значит что все компиляторы так делают.

 

Это очевидное заблуждение.

Почему?

В чём разница между:

char t[] = "XXXX";

и

void Func(char *)

?

И первом случае Вы говорите компилятору, что хотите иметь переменную (с начальным значением), а значит - хотите иметь возможность записи в неё. И во-втором случае говорите ему, что функция Func() хочет иметь возможность записи в принимаемый ею аргумент (т.е. - она принимает указатель на переменную). В чём принципиальная разница?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now