Member 12726564 Ответов: 3

Указатель char, инициализированный внутри тела функции, ведет ли он себя как статическая переменная?


void fun( char *s)
{
    char *p="Magic";
    int x=0;
    while(*(p+x)!='\0')
    {
         switch(*s)
        {
            case 'a':
            case 'e':
            case 'i':
            case 'o':
            case 'u':*s=++*p;
        }
        s++;x++;}
    //cout<<"The Data1 is \t"<<p<<endl;
}

void main()
{
    clrscr();
    char *st[]= {"Good","Logic"};
    for( int i=0;i<2;i++)
    {
        fun(*(st+i));
        cout<<"The Data2 is\t"<<st[i]<<endl; }
    getch();
}


Что я уже пробовал:

Каждый раз, когда функция вызывается, она сохраняет значение указателя p и исходит оттуда.

User 59241

Никакой указатель char не является статической переменной. Объясните свой вопрос полностью-Почему вы так думаете? Используйте вопрос улучшения.

Richard MacCutchan

Да, потому что вы инициализируете p чтобы указать на слово "Magic" в начале fun. Но p это все еще не статический указатель.

Philippe Mori

Нет особого смысла писать плохой код для такого вопроса, и код совсем не минималистичен... Около 75% кода совершенно бесполезны для ответа на этот вопрос.

3 Ответов

Рейтинг:
1

CPallini

Цитата:
char *p= " магия";
указатель char p это локальная (автоматическая) переменная, выделяемая в стек при каждом вызове функции.
Строка "Magic", который вы назначаете указателю, выделяется в памяти только для чтения. Приличный компилятор должен предупредить о таком назначении.


Philippe Mori

В Visual Studio нет предупреждений на уровне предупреждений по умолчанию, но во время выполнения происходит нарушение доступа на запись. Если char *p = "Magic"; меняется на char p[] = "Magic";, то код "работает"...

Philippe Mori

Кстати, та же проблема и с st...

CPallini

Конечно.

CPallini

Уровень предупреждения по умолчанию-зло :-)

Рейтинг:
0

KarstenK

Указатель - это только значение для адреса, которому он присвоен. Это больше не имеет смысла. Все смыслы должны быть реализованы вручную!!

Каждый раз, когда ваша функция вызывается, ваша "магия" p распределяется в куче, и если функция уничтожается, память освобождается. Это "свободный" означает, что сначала он может (но не должен) использоваться другой функцией. Не требуется, чтобы он был перезаписан. Так что ценность может оставаться вокруг - но у вас есть никакая гарантированность об этом. Не верь в это.

Вот почему работа с указателями опасна, поэтому вам лучше тщательно работать с ними.

Будьте осторожны: "сохранить" исходит от умных указателей или некоторых других языков высокого уровня со сборкой мусора и автоматическим подсчетом ссылок. В этих случаях назначение указателя увеличивает количество ссылок на объект.


Рейтинг:
0

Philippe Mori

Как указано в решении 2, Ваш код не будет работать, если компилятор поместит строки в память только для чтения.

Насколько я знаю и согласно моим тестам, код будет работать, если вместо него будут использоваться массивы (char p[] и char st[][6] Кстати, если используется последнее объявление, то память тратится впустую на более короткие строки. Фиксация этого оставлена как упражнение для читателя.

Я не вижу, где вы находите какое-либо статическое поведение. Отладив программу, можно легко увидеть, что p инициализируется с помощью "Magic" каждый раз, когда функция вызывается (как указано в решении 1).

Кстати, зачем вам использовать строку "Magic", если в коде используется только первый символ строки?

char p = 'M';
//...
*s = ++p;

это дало бы тот же результат, что и версия, не использующая строки только для чтения.

Между прочим ++*p увеличьте символ, а не указатель. Итак, м становится Н, затем О и т. д... И p всегда указывает на начало строки, которая будет "Oagic" после 2 обновлений.

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

Без static, (как только вы исправите нарушение доступа) вы получите:
The Data2 is    GNOd
The Data2 is    LNgOc


Добавление static к p ДЕКЛАРАЦИЯ, Вы получаете:
The Data2 is    GNOd
The Data2 is    LPgQc