Указатель арифметики указателя относительно матриц - PullRequest
0 голосов
/ 04 октября 2019

У меня есть сомнения относительно арифметики указателя в C.
Если мы сделаем

int ** ptr = 0x0;
printf("%p",ptr+=1);

Выход будет ptr + (количество байтов, необходимых для хранения указателя, в моемcase 8).
Теперь, если мы объявим матрицу:

int A[100][50];

A[0] - указатель указателя.
A[0]+1 теперь будет указывать на A [0] + (количество байтов, необходимое для хранения целого числа, в моем случае 4).
Почему "обычно" 8 байтов добавляются, а теперь 4? A[0]+1 будет указывать на A[0][1], так что это полезно, но как это работает?
Спасибо!

1 Ответ

1 голос
/ 05 октября 2019

Рассмотрим эту программу, работающую на 64-битной машине (Mac под управлением MacOS Mojave 10.14.6, если быть точным с GCC 9.2.0):

#include <stdio.h>

int main(void)
{
    int A[100][50];
    printf("Size of void * = %zu and size of int = %zu\n", sizeof(void *), sizeof(int));
    printf("Given 'int A[100][50];\n");
    printf("Size of A       = %zu\n", sizeof(A));
    printf("Size of A[0]    = %zu\n", sizeof(A[0]));
    printf("Size of A[0][0] = %zu\n", sizeof(A[0][0]));
    putchar('\n');
    printf("Address of A[0]     = %p\n", (void *)A[0]);
    printf("Address of A[0] + 0 = %p\n", (void *)(A[0] + 0));
    printf("Address of A[0] + 1 = %p\n", (void *)(A[0] + 1));
    printf("Difference          = %td\n", (void *)(A[0] + 1) - (void *)(A[0] + 0));
    putchar('\n');
    printf("Address of &A[0]     = %p\n", (void *)&A[0]);
    printf("Address of &A[0] + 0 = %p\n", (void *)(&A[0] + 0));
    printf("Address of &A[0] + 1 = %p\n", (void *)(&A[0] + 1));
    printf("Difference           = %td\n", (void *)(&A[0] + 1) - (void *)(&A[0] + 0));
    return 0;
}

Вывод:

Size of void * = 8 and size of int = 4
Given 'int A[100][50];
Size of A       = 20000
Size of A[0]    = 200
Size of A[0][0] = 4

Address of A[0]     = 0x7ffee5b005e0
Address of A[0] + 0 = 0x7ffee5b005e0
Address of A[0] + 1 = 0x7ffee5b005e4
Difference          = 4

Address of &A[0]     = 0x7ffee5b005e0
Address of &A[0] + 0 = 0x7ffee5b005e0
Address of &A[0] + 1 = 0x7ffee5b006a8
Difference           = 200

Следовательно, можно сделать вывод, что A[0] является массивом 50 int - это не «указатель указателя». Тем не менее, при использовании в выражении, таком как A[0] + 1, оно «распадается» на «указатель на int» (указатель на тип элемента массива), и, следовательно, A[0] + 1 - это значение на одно целое число дальшемассив.

Последний блок вывода показывает, что адрес массива имеет другой тип - int (*)[50] в случае A[0].

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