C указатель на массив / массив указателей неоднозначности

Концепция ведущих нулей - это концепция отображения, а не числовая. Вы можете поместить бесконечное число ведущих нулей на число без изменения его значения. Поскольку это не числовая концепция, она не сохраняется с номером.

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

446
задан akashchandrakar 12 December 2014 в 06:12
поделиться

5 ответов

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers

Третий такой же, как и первый.

Общее правило - приоритет оператора . Это может стать еще более сложным, когда на картинке появятся указатели на функции.

426
ответ дан 22 November 2019 в 23:05
поделиться

Я не знаю, есть ли у него официальное название, но я называю это Right-Left Thingy (TM).

Начните с переменной, затем идите вправо, влево, вправо ... и т. Д.

int* arr1[8];

arr1 - это массив из 8 указателей на целые числа.

int (*arr2)[8];

arr2 - указатель (скобки блокируют справа -left) в массив из 8 целых чисел.

int *(arr3[8]);

arr3 - это массив из 8 указателей на целые числа.

Это должно помочь вам со сложными объявлениями.

124
ответ дан 22 November 2019 в 23:05
поделиться

Используйте программу cdecl , предложенную K&R.

$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>

Она работает и в другом направлении.

cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
260
ответ дан 22 November 2019 в 23:05
поделиться

Ответ на два последних вопроса также можно вывести из золотого правила языка C:

Объявление следует за использованием.

int (* arr2) [8];

Что произойдет, если разыменовать arr2? У вас получится массив из 8 целых чисел.

int * (arr3 [8]);

Что произойдет, если вы возьмете элемент из arr3? Вы получаете указатель на целое число.

Это также помогает при работе с указателями на функции. Возьмем пример sigjuice:

float * (* x) (void)

Что происходит при разыменовании x? Вы получаете функцию, которую можно вызывать без аргументов. Что происходит, когда вы это называете? Он вернет указатель на число с плавающей запятой.

Однако с приоритетом оператора всегда сложно. Однако использование круглых скобок может сбивать с толку, потому что объявление следует за использованием. По крайней мере, для меня интуитивно arr2 выглядит как массив из 8 указателей на целые числа, но на самом деле все наоборот. Просто нужно привыкнуть. Достаточная причина, чтобы всегда добавлять комментарий к этим объявлениям, если вы спросите меня :)

edit: example

Кстати, я только что наткнулся на следующую ситуацию: функция, которая имеет статическую матрицу и использует арифметику указателей чтобы увидеть, выходит ли указатель строки за пределы. Пример:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i < 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}

Вывод:

0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]

Обратите внимание, что значение border никогда не меняется, поэтому компилятор может оптимизировать это. Это отличается от того, что вы могли бы изначально использовать: const int (* border) [3] : объявляет границу как указатель на массив из 3 целых чисел, который не будет изменять значение, пока переменная существуют. Однако этот указатель может указывать на любой другой такой массив в любое время.Вместо этого нам нужно такое поведение для аргумента (потому что эта функция не изменяет ни одно из этих целых чисел). Декларация следует за использованием.

(ps: не стесняйтесь улучшать этот образец!)

15
ответ дан 22 November 2019 в 23:05
поделиться
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
5
ответ дан 22 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: