Переменные указателя в круглых скобках [дубликат]

Вместо того, чтобы бросать код на вас, есть два понятия, которые являются ключом к пониманию того, как JS обрабатывает обратные вызовы и асинхронность. (это даже слово?)

Модель цикла события и параллелизма

Есть три вещи, о которых вам нужно знать; Очередь; цикл события и стек

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

while (queue.waitForMessage()) {
   queue.processNextMessage();
}

Как только он получает сообщение для запуска чего-то, он добавляет его в очередь. Очередь - это список вещей, которые ждут выполнения (например, ваш запрос AJAX). Представьте себе это так:

 1. call foo.com/api/bar using foobarFunc
 2. Go perform an infinite loop
 ... and so on

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

function foobarFunc (var) {
  console.log(anotherFunction(var));
}

. Так что все, что foobarFunc должно выполнить (в нашем случае anotherFunction), будет вставлено в стек. исполняемый, а затем забытый - цикл события затем переместится на следующую вещь в очереди (или прослушивает сообщения)

. Главное здесь - порядок выполнения. Это

КОГДА что-то будет запущено

Когда вы совершаете вызов с использованием AJAX для внешней стороны или выполняете любой асинхронный код (например, setTimeout), Javascript зависит от ответ, прежде чем он сможет продолжить.

Большой вопрос, когда он получит ответ? Ответ в том, что мы не знаем, поэтому цикл событий ждет, когда это сообщение скажет: «Эй, забери меня». Если JS просто ждал этого сообщения синхронно, ваше приложение замерзнет, ​​и оно сосать. Таким образом, JS продолжает выполнение следующего элемента в очереди, ожидая, пока сообщение не будет добавлено обратно в очередь.

Вот почему с асинхронной функциональностью мы используем вещи, называемые обратными вызовами. Это похоже на обещание буквально. Как и в I , обещание что-то вернуть в какой-то момент jQuery использует специальные обратные вызовы, называемые deffered.done deffered.fail и deffered.always (среди других). Вы можете увидеть их все здесь

Итак, вам нужно передать функцию, которая в какой-то момент будет выполнена с переданными ей данными.

Поскольку обратный вызов не выполняется немедленно, но в более позднее время важно передать ссылку на функцию, которую она не выполнила. поэтому

function foo(bla) {
  console.log(bla)
}

, поэтому большую часть времени (но не всегда) вы пройдете foo не foo()

. Надеюсь, это будет иметь смысл. Когда вы сталкиваетесь с такими вещами, которые кажутся запутанными, я настоятельно рекомендую полностью прочитать документацию, чтобы хотя бы понять ее. Это сделает вас намного лучшим разработчиком.

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

11 ответов

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

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

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

400
ответ дан Mehrdad Afshari 28 August 2018 в 08:30
поделиться

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

Декларация следует за использованием.

int (*arr2)[8];

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

int *(arr3[8]);

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

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

float *(*x)(void )

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

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

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]

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

(стр. См .: не стесняйтесь улучшать этот образец!) [/ ​​G14]

14
ответ дан 3 revs 28 August 2018 в 08:30
поделиться

Вот интересный веб-сайт, в котором объясняется, как читать сложные типы в C: http://www.unixwiz.net/techtips/reading-cdecl.html

0
ответ дан Abhishek Jaisingh 28 August 2018 в 08:30
поделиться

Я думаю, что мы можем использовать простое правило.

example int * (*ptr)()[];
start from ptr 

"ptr является указателем на« идти вправо ... »)« теперь идите налево »(« придите » out go right "()" so "для функции, которая не принимает аргументов« go left »и возвращает указатель« go right »в массив« go left »из целых чисел«

2
ответ дан akjoshi 28 August 2018 в 08:30
поделиться
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
5
ответ дан Byron Formwalt 28 August 2018 в 08:30
поделиться
int *a[4]; // Array of 4 pointers to int

int (*a)[4]; //a is a pointer to an integer array of size 4

int (*a[8])[5]; //a is an array of pointers to integer array of size 5 
24
ответ дан gary 28 August 2018 в 08:30
поделиться

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

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

int* arr1[8];

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

int (*arr2)[8];

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

int *(arr3[8]);

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

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

117
ответ дан GManNickG 28 August 2018 в 08:30
поделиться

Как правило, правые унарные операторы (например, [], () и т. д.) предпочитают более левые. Таким образом, int *(*ptr)()[]; будет указателем, который указывает на функцию, которая возвращает массив указателей на int (как можно скорее получить правильные операторы, когда вы выйдете из скобки)

2
ответ дан Luis Colorado 28 August 2018 в 08:30
поделиться

В указателе на целое число, если указатель увеличивается, он переходит в следующее целое число.

в массиве указателя, если указатель увеличивается, он переходит к следующему массиву

-7
ответ дан Nikhil 28 August 2018 в 08:30
поделиться

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

Позволяет иметь массив целых чисел, т. Е. int B[8].

Давайте также будем иметь переменную A, которая указывает на B. Теперь значение в A является B, т. е. (*A) == B. Следовательно, A указывает на массив целых чисел. В вашем вопросе arr похож на A.

Аналогично, в int* (*C) [8] C является указателем на массив указателей на целое число.

2
ответ дан nishantbhardwaj2002 28 August 2018 в 08:30
поделиться

Используйте программу cdecl , как предложено K & amp; 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 )
249
ответ дан Nisse Engström 28 August 2018 в 08:30
поделиться
Другие вопросы по тегам:

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