Причина для указателя указывает на последний символ строкового литерала во втором случае - PullRequest
0 голосов
/ 01 июля 2018

Дело 1:

# include<stdio.h>
int main() {
    int l=0;
    char *names[4] = {
        "Arijit",
        "Rohit",
        "Debojyoti",
        "Abhisek"
    };
    while(l<4)
    {
        printf("Address %u contains %s\n",names[l],names[l]);/*here instead of of names[l] for strings when I used names[l++] the memory order changed look at the output*/ 
        l++;
    }
    return 0;
}

вывод 1:

Address 4210688 contains Arijit
Address 4210695 contains Rohit
Address 4210701 contains Debojyoti
Address 4210711 contains Abhisek

вывод 2:

Address 4210695 contains Arijit
Address 4210701 contains Rohit
Address 4210711 contains Debojyoti
Address 45 contains Abhisek

Посмотрите на 2-й o / p Debojyoti содержит 10 символов, включая '\ 0', поэтому Рохиту присвоен адрес 4217011. Почему? Также посмотрите, Abhisek выделен для области памяти, которая не является последовательной для других трех имен. Почему?

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Проблема в том, что C не определяет порядок вычисления аргументов функции. Период. В большинстве случаев C не определяет порядок вычисления операндов бинарного оператора.

В результате обычно бывает ошибкой использовать и изменять переменную в одном выражении. (Для юристов по языку: Нет, я не имею в виду ошибку, которую обнаружит компилятор! Неопределенные ситуации поведения допустимы, но код по-прежнему ошибочен.)

Ваше утверждение второй версии, сокращенное, выглядит так:

    printf("%p, %s, %s\n", names[l], names[l], names[l++]);

C может оценивать эти аргументы до printf() в любом порядке. Это означает, что когда l==0 в начале размещения, любая из следующих интерпретаций этой первой итерации возможна:

    printf("%p, %s, %s\n", names[0], names[0], names[0]); l+=1;
    printf("%p, %s, %s\n", names[0], names[1], names[0]); l+=1;
    printf("%p, %s, %s\n", names[1], names[0], names[0]); l+=1;
    printf("%p, %s, %s\n", names[1], names[1], names[0]); l+=1;

На одном и том же компиляторе вы можете видеть разные порядки между отладочной и оптимизированной компиляцией. Средние две интерпретации маловероятны, но все же допускаются в компиляторе, соответствующем стандартам. Только 4-й аргумент гарантированно оценивается как names[0]', due to the definition of postfix ++ `.

Как я уже говорил выше, не используйте и не изменяйте одну и ту же переменную в одном выражении. Строго избегайте этого, когда порядок операций не гарантирован, и дважды подумайте даже в тех редких ситуациях, когда возможна только одна интерпретация. Гвидо Ван Россум (изобретатель языка Python) отмечает, что программы читаются чаще, чем пишутся. Есть определенная цена, связанная с тем, что вы запутаете другого программиста в вашей команде - или даже себя через год или два, когда вы вернетесь к редактированию кода.

Существует еще более серьезная цена, когда после тестирования компилятора начинает "проваливаться" производственный код.

0 голосов
/ 01 июля 2018

используя следующее:

printf("Address %u contains %s\n",names[l],names[l++])

дает результаты

Address 4195959 contains Arijit
Address 4195965 contains Rohit
Address 4195975 contains Debojyoti
Address 2973903200 contains Abhisek

почему это? потому что имена [l ++] в этом случае оцениваются перед именами [l]. Я получаю l + 1 и при использовании имен [l], следующий l используется вместо того, что вы ожидали. По этой же причине фамилия [l] содержит мусор

с использованием следующего:

printf("Address %u contains %s\n",names[l++],names[l]);

дает (правильные) результаты:

Address 4195952 contains Arijit
Address 4195959 contains Rohit
Address 4195965 contains Debojyoti
Address 4195975 contains Abhisek

Теперь оценка выполняется после обоих имен [] оценка

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

...