Разница между ** (x + i) и * (* x + i) - PullRequest
       1

Разница между ** (x + i) и * (* x + i)

0 голосов
/ 23 сентября 2019

Я использую массив указателей, где каждый индекс содержит указатель, который указывает на массив целых чисел.Хотя мне удалось выяснить, как печатать значения в массиве с помощью массива указателей, есть одна строка кода, в которой мне нужно внести ясность.Я хочу понять разницу между ** (x + i) и * (* x + i), поскольку первый генерирует исключение ошибки сегментации, в то время как последний печатает желаемый результат.Пожалуйста, обратитесь к моему примеру кода ниже.

int pointer_array=malloc(1*sizeof(int*));
int number_array = malloc(2*sizeof(int));
*(pointer_array)=number_array; 
for(int i=0;i<2;i++) {
  *(pointer_array+i)=i;
}
for(int i=0;i<2;i++) {
  //printf("\n%d",**(pointer_arr+i));  This throws Segmentation Fault exception
    printf("\n%d",*(*pointer_arr+i)); // This prints the desired output 0 \n 1
}

Ответы [ 3 ]

6 голосов
/ 23 сентября 2019

Разница между выражениями становится очень очевидной, если мы преобразуем их в нотацию массива, используя *(a + i) == a[i] эквивалентность и ее следствие *a == a[0].

**(x + i) равно x[i][0], тогда как *(*x + i) is x[0][i].

В вашем коде мы хотим это:

#include <stdlib.h>

int **pointer_array = malloc(1*sizeof(int*));
    ^^

int *number_array = malloc(2*sizeof(int));
    ^

Тогда остальная часть кода означает это:

*(pointer_array)=number_array; // pointer_array[0] = number_array

Упс:Цикл присваивает указателям целые числа:

for(int i=0;i<2;i++) {
  *(pointer_array+i)=i;  // pointer_array[i] = i
}

Выше, вероятно, предполагается, что number_array[i] = i.

for(int i=0;i<2;i++) {

  printf("\n%d",*(*pointer_arr+i)); // printf ... pointer_arr[0][i]
}

Если мы исправим первый цикл для инициализации number_array, то этот второйцикл должен получить эти значения.

В противном случае мы переходим к неинициализированным значениям.

0 голосов
/ 23 сентября 2019

Ваш код небезопасен;malloc вернет void * - тип указателя.Вы сохраняете результаты в int.int не гарантированно будет достаточно большим, чтобы хранить void *, и действительно не будет на x86, текущей преобладающей архитектуре.

При этом:

  • (x+i), если x является указателем, будет равен i*sizeof(*x) + x.Таким образом, он будет вычислять указатель с i-ю слотами после x;
  • **(x+i), следовательно, будет считывать указатель из i-х слотов после x, а затем считывать все, на что указывает этот указатель.

Таким образом, из массива указателей на массивы он будет читать первый элемент из i th массива.

Принимая во внимание:

  • *x+i будет читать указатель изx, а затем добавьте к нему i * sizeof (** x);
  • *(*x+i) будет читать указатель оттуда и разыменовывать его.

Итак, из массивауказатели на массивы, он будет читать i i-й элемент из первого массива.

0 голосов
/ 23 сентября 2019

**(x+i) означает «оценить x+i, который даст указатель, затем прочитает значение, на которое он указывает, который даст другой указатель, затем прочитает значение, на которое он указывает», или, что эквивалентно, x[i][0],*(*x+i) означает «оценить x, который даст указатель, затем прочитает значение, на которое он указывает, который даст другой указатель, затем добавит к этому i, затем прочитает значение, на которое он указывает», илиэквивалентно x[0][i].Очевидно, это очень разные выражения.

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