Инициализация указателя и два указателя, указывающие на один и тот же адрес - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь лучше понять указатели.У меня есть этот кусок кода:

char theString[MAX] = "All your base are belong to us";
char *i = theString;
char *j = theString;
printf("%p\n", &theString);
printf("%p\n", &i);
printf("%p\n", &j);

Когда я запускаю свою программу, я всегда получаю три отдельных адреса.Я понимаю, что адреса памяти меняются каждый раз, когда я компилирую и не являются статичными;но, поскольку я установил i и j в качестве адреса первого символа в «theString», я бы предположил, что они будут иметь одинаковый адрес?

Любая помощь очень ценится, спасибо.

Ответы [ 6 ]

2 голосов
/ 09 апреля 2019

Когда я запускаю свою программу, я всегда получаю три отдельных адреса.

Вы распечатали адреса трех разных вещей: i, j и theString. Если вы напечатаете значения из i и j, вы обнаружите, что они оба указывают на theString. Оператор & принимает адрес самих переменных i и j.

Вот ваши операторы печати, модифицированные для отображения переменных в обоих направлениях:

printf("With &:%p\tWithout &:%p\n", &theString, theString);
printf("With &:%p\tWithout &:%p\n", &i, i);
printf("With &:%p\tWithout &:%p\n", &j, j);

И вывод:

With &:0x7ffeefbfee20   Without &:0x7ffeefbfee20
With &:0x7ffeefbfee08   Without &:0x7ffeefbfee20
With &:0x7ffeefbfee00   Without &:0x7ffeefbfee20

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

1 голос
/ 09 апреля 2019

&j и &i - это адреса указателей, а не объекта, на который они ссылаются

printf("%p\n", (void *)i);
printf("%p\n", (void *)&j);

То же, что и int a = 3; и int b = 3;, вы не ожидаете, что &a будет таким же, как &b

0 голосов
/ 09 апреля 2019

Обратите внимание, что i и j указывают на строку, имеющую собственную память.Вот почему они имеют разную ценность.Но значения i, j и theString будут одинаковыми, что указывает на массив символов.

printf("%p\n", theString);
printf("%p\n", i);
printf("%p\n", j);

Вывод:

0x8efeefbfee50
0x8efeefbfee50
0x8efeefbfee50
0 голосов
/ 09 апреля 2019

относительно:

printf("%p\n", &theString);  

В C ссылка на имя массива ухудшается до адреса первого байта массива, поэтому нет необходимости использовать оператор 'address of'. Компилятор пожалуется:

: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘char (*)[##]’ [-Wformat=] 

где '##' - количество элементов в массиве

0 голосов
/ 09 апреля 2019
i and j are char pointers , nothing but variables in short and like every variable they have their own locations and hence, their own addresses.

These variables hold the address of theString and hence both point to the same address

When you print &i and &j , it prints out the address of i and j in memory and hence, you get different addresses. But they hold the address of the same variable

Your code prints out the address of the array theString , pointer i address and pointer j address.


char theString[MAX] = "All your base are belong to us";
char *i = theString;
char *j = theString;
printf("%p\n", &theString);
printf("%p\n", &i);
printf("%p\n", &j);
0 голосов
/ 09 апреля 2019

Попробуйте:

printf("Address of theString = %p, value of theString = %s\n", (void *) theString, theString);
printf("Address of i = %p, value of i = %p\n", (void *) &i, (void *) i );
printf("Address of j = %p, value of j = %p\n", (void *) &j, (void *) j );

theString, i и j - все отдельные объекты в памяти, поэтому они будут иметь разные адреса.i и j будут иметь одинаковое значение , то есть адрес theString.

Некоторые примечания:

  • За исключением случаев, когда он является операндом операторов sizeof или унарных & или является строковым литералом, используемым для инициализации массива символовв объявлении выражение типа «массив N-элементов из T» будет преобразовано («распад») в выражение типа «указатель на T» и значениевыражение будет адресом первого элемента.Таким образом, в первом операторе printf вам не нужен оператор & для получения адреса theString.Оба выражения theString и &theString будут вычисляться по адресу первого элемента массива, но типы выражений будут разными (char * против char (*)[MAX]).

  • Спецификатор преобразования %p ожидает, что его соответствующий аргумент будет иметь тип void *.Это единственное место в C, где вам нужно явно привести выражение указателя к void *.

  • Типы i и j равны char *, поэтому типы выражений &i и &j равны char **,

РЕДАКТИРОВАТЬ

Я взял ваши объявления и запустил их через собственную утилиту дампа памяти:

#include "dumper.h"

#define MAX 32

int main( void )
{
  char theString[MAX+1] = "All your base are belong to us";
  char *i = theString;
  char *j = theString;

  char *names[] = {"theString", "i", "j" };
  void *addrs[] = {theString, &i, &j};
  size_t sizes[] = { sizeof theString, sizeof i, sizeof j };

  dumper( names, addrs, sizes, 3, stdout );

  return 0;
}

И вотвывод:

       Item         Address   00   01   02   03
       ----         -------   --   --   --   --
  theString  0x7ffee727fa90   41   6c   6c   20    All.
             0x7ffee727fa94   79   6f   75   72    your
             0x7ffee727fa98   20   62   61   73    .bas
             0x7ffee727fa9c   65   20   61   72    e.ar
             0x7ffee727faa0   65   20   62   65    e.be
             0x7ffee727faa4   6c   6f   6e   67    long
             0x7ffee727faa8   20   74   6f   20    .to.
             0x7ffee727faac   75   73   00   00    us..
             0x7ffee727fab0   00   00   00   00    ....

          i  0x7ffee727fa20   90   fa   27   e7    ..'.
             0x7ffee727fa24   fe   7f   00   00    ....

          j  0x7ffee727fa18   90   fa   27   e7    ..'.
             0x7ffee727fa1c   fe   7f   00   00    ....

x86 имеет младший порядок, поэтому многобайтовые значения нужно читать справа налево, снизу вверх.Вы увидите, что i и j содержат одно и то же значение (0x7ffee727fa90), которое является адресом первого элемента theString.

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