Базовая помощь, необходимая с указателями (двойное обращение) - PullRequest
3 голосов
/ 15 марта 2010

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

например

char *ptr = "hello" (hello = a char array)

так что теперь * ptr указывает на h

ptr++ = перемещает ptr для указания на следующий элемент, чтобы получить его значение, которое я делаю * ptr, и это дает мне

Хорошо, пока, я надеюсь: D, но теперь мне нужно манипулировать char **ptr, и мне было интересно, как я делаю это таким образом, который имитирует эффекты двумерного массива?

Некоторые базовые советы будут высоко оценены, так как мне нужно выполнить задание, которое имеет **ptr для имитации 2d-массива, и, не зная, как это происходит, означает, что я даже не могу решить его на бумаге (например, вы разыменовываете ** ptr, как вы получаете значения [x] [y] и т. д.)

спасибо

Ответы [ 3 ]

9 голосов
/ 15 марта 2010

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

При условии следующего объявления:

char **ptr;

Вот типы различных выражений:

       Expression        Type      Equivalent expressions (yield same value)     
       ----------        ----      -----------------------------------------
              ptr        char **   &ptr[0]
             *ptr        char *    ptr[0] 
         *(ptr+i)        char *    ptr[i]; &ptr[i][0]
            **ptr        char      ptr[0][0]
      *(*(ptr+i))        char      ptr[i][0]; *ptr[i]
    *(*(ptr+i)+j)        char      ptr[i][j]

следующим образом:

  • ptr можно трактовать , как если бы это был массив строк (2-й массив символов)
  • ptr[i] указывает на начало i-й строки в списке
  • ptr[i][j] - значение j-го символа i-й строки в списке
  • Выражения ptr++ и ++ptr будут продвигаться ptr, чтобы указывать на следующую строку
  • Выражения (*ptr)++ и ++(*ptr) будут продвигаться *ptr, чтобы указывать на следующий символ

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

char **ptr = {"foo", "bar", "bletch"}; // using aggregate initializer on 
                                       // non-aggregate type; bad juju,
                                       // a.k.a undefined behavior

или

char **ptr;          // ptr has not been initialized to point anywhere 
ptr[0] = "foo";      // dereferencing ptr via subscript invokes undefined
ptr[1] = "bar";      // behavior
ptr[2] = "bletch";

Как правило, когда вы используете указатель, как если бы он был массивом, вы будете использовать malloc или что-то подобное для распределения ваших буферов:

char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
  ptr[0] = "foo";    // ptr[i] gets address of
  ptr[1] = "bar";    // string literal
  ptr[2] = "bletch";
  ...
}

или

char **ptr = malloc(sizeof *ptr * N);
if (ptr)
{
  size_t i;
  for (i = 0; i < N; i++)
  {
    ptr[i] = malloc(sizeof *ptr[i] * M); // strictly speaking, the sizeof
    if (ptr[i])                          // is not necessary here
    {
      //initialize ptr[i]
    }
  }
}
4 голосов
/ 15 марта 2010

Указатель на указатель - только это. Например:

// Declare our double-indirection pointer.
char** ptr;
// And initialize it:
char s1[] = "hello";
char s2[] = "world";
ptr = malloc(sizeof(char*) * 2);
ptr[0] = s1;
ptr[1] = s2;
// ptr now points to a pointer that points to 'h'.
char* ptr2 = *ptr;
// ptr2 points to 'h'.
char* ptr3 = *(ptr + 1);
// ptr3 points to "w".
char c = **ptr; // could be written as *(*ptr)
// c = 'h'.
char c2 = *(*(ptr + 1));
// c2 = 'w'.
char c3 = *(*(ptr) + 1);
// c3 = 'e'.
1 голос
/ 15 марта 2010

Вы можете использовать их так же, как обычный двумерный массив. (Так как по сути, это то, что они есть)

char** ptr = {"lorem", "ipsum", "dolor"};
char* s1 = ptr[0]; //Points to the beginning of "lorem"
char* s2 = ptr[1]; //Points to the beginning of "ipsum"
char c = ptr[2][4]; //Contains 'r'

Это связано с тем, что:

int *a;
//...
int i = a[6];
int j = *(a + 6); //Same as previous line!

Приветствия

Амит Рон -

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