почему указатель имеет 12 различий в следующей ячейке памяти - PullRequest
0 голосов
/ 07 сентября 2018

почему нижеприведенная программа, принимающая разницу в памяти к следующему местоположению, исправляет 12 в следующей ячейке памяти или имеет некоторую логику для char / float / int, имеющей разность -2, отличающуюся от следующего местоположения

включают # Включают

int main () {

   char  var;
   char  *ptr;
   char  **pptr;
    char  ***ppptr;
   char  ****pppptr;

   var = 'M';

   /* take the address of var */
   ptr = &var;

   /* take the address of ptr using address of operator & */
   pptr = &ptr;

   ppptr=&pptr;

   ppptr=&pptr;
   ppptr=&pptr;
   pppptr=&ppptr;

   /* take the value using pptr */
   printf("Value of var = %d\n", var );
   printf("Value available at *ptr = %c....and address is %u\n", *ptr ,ptr);
   printf("Value available at **pptr = %c....and address is %u\n", **pptr,pptr);
   printf("Value available at ***ppptr = %c....and address is %u\n", ***ppptr ,ppptr);
   printf("Value available at ****pppptr = %c....and address is %u\n", ****pppptr,pppptr);
   getch();
   return 0;
}
//out put
///-----------------------------------------------
Value of var = 77;
Value available at *ptr = M....and address is 11401207
Value available at **pptr = M....and address is 11401192   why differnceis 12 in memory locaton 
Value available at ***ppptr = M....and address is 11401180
Value available at ****pppptr = M....and address is 11401168

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Вы, кажется, спрашиваете, почему адрес ptr, судя по печати значения pptr с использованием дескриптора поля scanf %u, отличается от адреса следующей объявленной локальной переменной , pptr, на 12 байтов. И так далее для других локальных переменных, я полагаю.

Фактически, как @SouravGhosh уже описал в своем ответе, дескриптор поля %u не соответствует должным образом аргументам указателя, и, следовательно, эффекты ваших вызовов scanf, включая все аспекты вывода, не определены.

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

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

0 голосов
/ 07 сентября 2018

Во-первых, правильный способ печати указателей - с помощью %p и с указателем, преобразованным в void * при передаче в printf, как в printf("%p\n", (void *) ptr);. Поскольку вы упоминаете в комментарии, что использовали %P, в отличие от %u, показанного в вопросе, я предполагаю, что неверный случай является опечаткой, и вы воспроизвели проблему, используя %p с результатами, аналогичными показанным в вопрос.

В этом случае вероятно то, что компилятор хранит указатели ptr, pptr, ppptr и pppptr по адресам, которые находятся на расстоянии 12 байтов друг от друга. Конечно, он мог бы хранить их всего в четырех или восьми байтах друг от друга, если бы указатели в вашей реализации C имели размер четыре или восемь байтов. Однако компилятор может хранить между указателями другие вещи, например адреса строк, которые вы используете в операторах printf, или другие случайные значения. Это заставляет меня подозревать, что вы скомпилировали без включенной оптимизации. Если вы перекомпилируете с оптимизацией, вы, скорее всего, увидите другие результаты.

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

0 голосов
/ 07 сентября 2018

Использование %u для печати адреса указателя приводит к неопределенному поведению .

Используйте %p спецификатор формата и приведите аргумент к void *.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...