В чем разница между * pt в int (* pt) [2] и pt в int * pt? - PullRequest
1 голос
/ 29 сентября 2019

Например

    int (*pt)[4];
    int target[3][4] = {{1,3,4,6},{2,4,5,8},{3,4,6,7}};
    pt = target;
    *pt = target[0];

почему это «[Ошибка] недопустимое присвоение массива»

Ответы [ 3 ]

3 голосов
/ 29 сентября 2019

int (*pt)[4] объявляет pt как указатель на массив.

C не позволяет назначать массивы;например, вы не можете сделать:

int a[4] = {1, 2, 3, 4};
int b[4];
b = a;

Если вы хотите скопировать массив, вам нужно использовать цикл, или вы можете использовать memcpy:

memcpy(pt, target[0], sizeof target[0]);
2 голосов
/ 29 сентября 2019

Слегка добавляя к превосходному ответу, данному Бармаром,

int (*pt)[4];

объявляет указатель на массив int [4]

int target[3][4] = {{1,3,4,6},{2,4,5,8},{3,4,6,7}};

объявляет массив массивов int [4] (3 из них в общем двумерном массиве)

pt = target;

при доступе target преобразуется в указатель на свой первый элемент.(преобразование массива / указателя) Так как его первый элемент представляет собой массив из int [4] , он преобразуется в указатель на массив из int [4] , который является type-совместим с pt.См. C11 Standard - 6.3.2.1 Другие операнды - L-значения, массивы и указатели функций (p3)

*pt = target[0];

, поскольку pt является указателем на массив int [4] , когда вы разыменовываете указатель, вы получаете массив из int [4] - и массивы не являются lvalues ​​и не могут быть назначены. Id at (p1) .

1 голос
/ 29 сентября 2019

ОП задал два вопроса.

Вопрос 1

В чем разница между *pt в int (*pt)[2]и pt в int *pt?

В этом

int (*pt)[4];

pt - указатель, который может указывать на массив из 4 целых чисел.

Предположим, массив 4 целое число - int arr[4] = {1,3,4,6};

Вы можете сделать

pt = &arr;  //pt is now pointing to array arr.

В контексте вашей программы

pt = target;

это эквивалентнов

pt = &target[0];

, потому что target - это адрес первого элемента массива, который является массивом 1D:

target  ->  target + 0  ->  &(*(target + 0)  ->  &target[0]

, а target[0] - это массив 4 целых чисел.

Обратите внимание, что тип из *pt равен int [4], и когда вы используете *pt в своей программе, вы получите адрес первого элемента массива, на который он указывает и который такжебазовый адрес массива:

*pt  ->  *pt + 0  ->  &(*(*pt + 0))  ->  &(*pt)[0]

Учтите это

#include <stdio.h>

int main (void)
{
    int (*pt)[4];
    int target[3][4] = {{1,3,4,6},{2,4,5,8},{3,4,6,7}};
    pt = target;  // pointer pt pointing to target[0] array
    printf ("%p\n", (void *)*pt);
    printf ("%p\n", (void *)&target[0][0]);
    return 0;
}

Вывод:

# ./a.out
0x7ffee35389e0
0x7ffee35389e0

Приходит к 2 и часть вопросав этом утверждении

int *pt;

Здесь pt - указатель нацелое число.

Предположим, у вас есть массив 4 целое число - int arr[4] = {1,3,4,6};

Когда вы делаете

pt = arr;

эквивалентно

pt = *arr[0];

потому что

arr  ->  arr + 0  ->  &(*(arr + 0))  ->  &arr[0]

Итак, *pt даст значение по адресу, на который он указывает.

Рассмотрим этот пример:

#include <stdio.h>

int main (void)
{
    int *pt;
    int arr[4] = {1,3,4,6};
    pt = arr;
    printf ("%p\n", (void *)pt);
    printf ("%p\n", (void *)arr);
    printf ("%p\n", (void *)&arr[0]);
    printf ("%d\n", *pt);
    return 0;
}

Вывод:

# ./a.out
0x7ffee86f0a00
0x7ffee86f0a00
0x7ffee86f0a00
1

Вопрос 2

почему это «[Ошибка] неверное присвоение массива»

*pt = target[0];

Обратите внимание, что pt является указателем на массив целых чисел 4.Тип *pt - int [4].Имя массива не является изменяемым lvalue, и вы не можете присвоить ему.Следовательно, компилятор выдает ошибку в этом утверждении.

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