admin / 02.12.2017

Указатели в си

Указатели в Си.

Пожалуйста, приостановите работу AdBlock на этом сайте.

Указатель – переменная, в которой хранится адрес какого-либо объекта в памяти компьютера, например, другой переменной. Мы уже сталкивались раньше с адресами переменных, когда изучали функцию scanf.

Итак, пойдём по порядку. Объявление указателя.

Объявление указателя отличается от объявления переменной только добавлением символа * после названия типа. Примеры:

Листинг 1.

int * p_g; // указатель на переменную типа int double * p_f; // указатель на переменную типа double

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

Листинг 2.

int n = 100; double PI = 3.1415926; int * p_k; // указатель на переменную типа int double * p_pi; // указатель на переменную типа double p_k = &n; // получаем адрес переменной n и присваиваем его указателю p_k p_pi = Π // получаем адрес переменной PI и присваиваем его указателю p_pi

Для вывода значения указателя на экран нужно в функции printf использовать модификатор %p. Пример:

Листинг 3.

printf ("adres peremennoi PI %p\n", p_pi);

Используя адрес переменной, который хранится в указателе, можно изменять значения этой переменной. Для этого используется операция разыменования *. Вот посмотрите на пример:

Листинг 4.

#include <stdio.h> int main(void) { int a = 100; int * p_a = &a; // сохраняем в указатель адрес переменной a printf("a = %d\n", a); // стандартный способ получить значение переменной a printf("a = %d\n", *p_a); // получаем значение переменной a через указатель на неё // используя указатель p_a, записываем в переменную a другое значение *p_a = 50; printf("a = %d\n", *p_a); return 0; }

Рис.1 Доступ к переменной через указатель

Итого, * применительно к указателям используется в двух случаях:

  • при объявлении указателя, чтобы показать, что это указатель;
  • если мы хотим обратиться к переменной, на которую указывает указатель.

Есть еще, так называемый, нулевой указательNULL. Нулевой указатель не ссылается никуда. Он используется, чтобы обнулять указатели. Посмотрите на пример.

Листинг 5.

#include <stdio.h> int main(void) { int a = 100; int * p_a = &a; // сохраняем в указатель адрес переменной a printf("a = %d\n", a); // стандартный способ получить значение переменной a printf("a = %d\n", *p_a); // получаем значение переменной a через указатель на неё // используя указатель p_a, записываем в переменную a другое значение *p_a = 50; printf("a = %d\n", *p_a); printf("%p\n", p_a); p_a = NULL; printf("%p\n", p_a); return 0; }

Рис.2 Обнуление указателя

На главную

Язык Си на примерах

Функции в Си

Для чего нужны функции в C?

Функции в Си применяются для выполнения определённых действий в рамках общей программы. Программист сам решает какие именно действия вывести в функции. Особенно удобно применять функции для многократно повторяющихся действий.

Простой пример функции в Cи

Пример функции в Cи:

Это очень простая программа на Си. Она просто выводит строку «Functions in C». В программе имеется единственная функция под названием main. Рассмотрим эту функцию подробно. В заголовке функции, т.е. в строке

int main(void)

int – это тип возвращаемого функцией значения;

main — это имя функции;

(void) — это перечень аргументов функции. Слово void указывает, что у данной функции нет аргументов;

return – это оператор, который завершает выполнение функции и возвращает результат работы функции в точку вызова этой функции;

EXIT_SUCCESS — это значение, равное нулю. Оно определено в файле stdlib.h;

часть функции после заголовка, заключенная в фигурные скобки

{
     puts(«Functions in C»);
     return EXIT_SUCCESS;
}

называют телом функции.

Итак, когда мы работаем с функцией надо указать имя функции, у нас это main, тип возвращаемого функцией значения, у нас это int, дать перечень аргументов в круглых скобках после имени функции, у нас нет аргументов, поэтому пишем void, в теле функции выполнить какие-то действия (ради них и создавалась функция) и вернуть результат работы функции оператором return. Вот основное, что нужно знать про функции в C.

Как из одной функции в Cи вызвать другую функцию?

Рассмотрим пример вызова функций в Си:

Запускаем на выполнение и получаем:

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

Заголовок функции sum:

int sum(int a, int b)

здесь int — это тип возвращаемого функцией значения;

sum — это имя функции;

(int a, int b) — в круглых скобках после имени функции дан перечень её аргументов: первый аргумент int a, второй аргумент int b. Имена аргументов являются формальными, т.е. при вызове функции мы не обязаны отправлять в эту функцию в качестве аргументов значения перемнных с именами a и b. В функции main мы вызываем функцию sum так: sum(d, e);. Но важно, чтоб переданные в функцию аргументы совпадали по типу с объявленными в функции.

В теле функции sum, т.е. внутри фигурных скобок после заголовка функции, мы создаем локальную переменную int c, присваиваем ей значение суммы a плюс b и возвращаем её в качестве результата работы функции опрератором return.

Теперь посмотрим как функция sum вызывается из функции main.

Вот функция main:

Сначала мы создаём две переменных типа int

int d = 1; int e = 2;

их мы передадим в функцию sum в качестве значений аргументов.

Далее создаём переменную f:

int f = sum(d, e);

её значением будет результат работы функции sum, т.е. мы вызываем функцию sum, которая возвратит значение типа int, его-то мы и присваиваем переменной f. В качестве аргументов передаём d и f. Но в заголовке функции sum

int sum(int a, int b)

аргументы называются a и b, почему тогда мы передаем d и f? Потому что в заголовке функций пишут формальные аргументы, т.е. НЕ важны названия аргументов, а важны их типы. У функции sum оба аргумента имеют тип int, значит при вызове этой функции надо передать два аргумента типа int с любыми названиями.

Ещё одна тонкость. Функция должна быть объявлена до места её первого вызова. В нашем примере так и было: сначала объявлена функция sum, а уж после мы вызываем её из функции main. Если функция объявляется после места её вызова, то следует использовать прототип функции.

Прототип функции в Си

Рассмотрим пример функциив Си:

В этом примере функция sum определена ниже места её вызова в функции main.

В таком случае надо использовать прототип функции sum. Прототип у нас объявлен выше функции main:

int sum(int a, int b);

Прототип — это заголовок функции, который завершается точкой с запятой. Прототип — это объявление функции, которая будет ниже определена. Именно так у нас и сделано: мы объявили прототип функции

int sum(int a, int b);

далее в функции main вызываем функцию sum

int f = sum(d, e);

а ниже функции main определяем функцию sum, которая предварительно была объявлена в прототипе:

Чем объявление функции в Си отличается от определения функции в Си?

Когда мы пишем прототип функции, например так:

int sum(int a, int b);

то мы объявляем функцию.

А когда мы реализуем функцию, т.е. записываем не только заголовок, но и тело функции, например:

то мы определяем функцию.

Оператор return

Оператор return завершает работу функции в C и возвращает результат её работы в точку вызова. Пример:

Эту функцию можно упростить:

здесь оператор return вернёт значение суммы a + b.

Операторов return в одной функции может быть несколько. Пример:

Если в примере значение аргумента a окажется больше двух, то функция вернет ноль (первый случай) и всё, что ниже комментария «// Первый случай;» выполнятся не будет.

Указатели в языке Си

Если a будет меньше двух, но b будет меньше нуля, то функция завершит свою работу и всё, что ниже комментария «// Второй случай;» выполнятся не будет.

И только если оба предыдущих условия не выполняются, то выполнение программы дойдёт до последнего оператора return и будет возвращена сумма a + b.

Передача аргументов функции по значению

Аргументы можно передавать в функцию C по значению. Пример:

В примере, в функции main, создаём переменную int d = 10. Передаём по значению эту переменную в функцию sum(d). Внутри функции sum значение переменной увеличивается на 5. Но в функции main значение d не изменится, ведь она была передана по значению. Это означает, что было передано значение переменной, а не сама переменная. Об этом говорит и результат работы программы:

т.е. после возврата из функции sum значеие d не изменилось, тогда как внутри функции sum оно менялось.

Передача указателей функции Си

Если в качестве аргумента функции передавать вместо значения переменной указатель на эту переменную, то значение этой переменной может меняться. Для примера берём программу из предыдущего раздела, несколько изменив её:

В этом варианте программы я перешел от передачи аргумента по значению к передаче указателя на переменную. Рассмотрим подробнее этот момент.

В строке

printf(«sum = %d\n», sum(&d));

в функцию sum передается не значение переменной d, равное 10-ти, а адрес этой переменной, вот так:

sum(&d)

Теперь посмотрим на функцию sum:

Аргументом её является указатель на int. Мы знаем, что указатель — это переменная, значением которой является адрес какого-то объекта. Адрес переменной d отправляем в функцию sum:

sum(&d)

Внутри sum указатель int *a разыменовывается. Это позволяет от указателя перейти к самой переменной, на которую и указывает наш указатель. А в нашем случае это переменная d, т.е. выражение

a += 5;

равносильно выражению

d += 5;

Результат: функция sum изменяет значение переменной d:

На этот раз изменяется значение d после возврата из sum, чего не наблюдалось в предыдущм пункте, когда мы передавали аргумент по значению.

C/C++ в Eclipse

Все примеры для этой статьи я сделал в Eclipse. Как работать с C/C++ в Eclipse можно посмотреть здесь. Если вы работаете в другой среде, то примеры и там будут работать.

Теги: Си указатели. Указатель на указатель. Тип указателя. Арифметика указателей. Сравнение указателей.

Указатели

Это, пожалуй, самая сложная и самая важная тема во всём курсе. Без понимания указателей дальнейшее изучении си будет бессмысленным. Указатели – очень простая концепция, очень логичная, но требующая внимания к деталям.

Определение

Указатель – это переменная, которая хранит адрес области памяти.

Тема 7. Указатели в Си.

Указатель, как и переменная, имеет тип. Синтаксис объявления указателей

<тип> *<имя>;

Например
Два основных оператора для работы с указателями – это оператор & взятия адреса, и оператор * разыменования. Рассмотрим простой пример.

#include <conio.h> #include <stdio.h> void main() { int A = 100; int *p; //Получаем адрес переменной A p = &A; //Выводим адрес переменной A printf(«%p\n», p); //Выводим содержимое переменной A printf(«%d\n», *p); //Меняем содержимое переменной A *p = 200; printf(«%d\n», A); printf(«%d», *p); getch(); }

Рассмотрим код внимательно, ещё раз

int A = 100;

Была объявлена переменная с именем A. Она располагается по какому-то адресу в памяти. По этому адресу хранится значение 100.

int *p;

Создали указатель типа int.

p = &A;

Теперь переменная p хранит адрес переменной A. Используя оператор * мы получаем доступ до содержимого переменной A.
Чтобы изменить содержимое, пишем

*p = 200;

После этого значение A также изменено, так как она указывает на ту же область памяти. Ничего сложного.
Теперь другой важный пример

#include <conio.h> #include <stdio.h> void main() { int A = 100; int *a = &A; double B = 2.3; double *b = &B; printf(«%d\n», sizeof(A)); printf(«%d\n», sizeof(a)); printf(«%d\n», sizeof(B)); printf(«%d\n», sizeof(b)); getch(); }

Будет выведено
Несмотря на то, что переменные имеют разный тип и размер, указатели на них имеют один размер. Действительно, если указатели хранят адреса, то они должны быть целочисленного типа. Так и есть, указатель сам по себе хранится в переменной типа size_t (а также ptrdiff_t), это тип, который ведёт себя как целочисленный, однако его размер зависит от разрядности системы. В большинстве случаев разницы между ними нет. Зачем тогда указателю нужен тип?

Арифметика указателей

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

Для их выполнения необходимо знать размер.
операция сдвигает указатель вперёд на байт.
Например, если указатель int *p; хранит адрес CC02, то после p += 10; он будет хранить адрес СС02 + sizeof(int)*10 = CC02 + 28 = CC2A (Все операции выполняются в шестнадцатиричном формате). Пусть мы создали указатель на начало массива. После этого мы можем «двигаться» по этому массиву, получая доступ до отдельных элементов.

#include <conio.h> #include <stdio.h> void main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *p; p = A; printf(«%d\n», *p); p++; printf(«%d\n», *p); p = p + 4; printf(«%d\n», *p); getch(); }

Заметьте, каким образом мы получили адрес первого элемента массива

p = A;

Массив, по сути, сам является указателем, поэтому не нужно использовать оператор &. Мы можем переписать пример по-другому

p = &A[0];

Получить адрес первого элемента и относительно него двигаться по массиву.
Кроме операторов + и — указатели поддерживают операции сравнения. Если у нас есть два указателя a и b, то a > b, если адрес, который хранит a, больше адреса, который хранит b.

#include <conio.h> #include <stdio.h> void main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int *a, *b; a = &A[0]; b = &A[9]; printf(«&A[0] == %p\n», a); printf(«&A[9] == %p\n», b); if (a < b) { printf(«a < b»); } else { printf(«b < a»); } getch(); }

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

Указатель на указатель

Указатель хранит адрес области памяти. Можно создать указатель на указатель, тогда он будет хранить адрес указателя и сможет обращаться к его содержимому. Указатель на указатель определяется как

<тип> **<имя>;

Очевидно, ничто не мешает создать и указатель на указатель на указатель, и указатель на указатель на указатель на указатель и так далее. Это нам понадобится при работе с двумерными и многомерными массивами. А вот простой пример, как можно работать с указателем на указатель.

#include <conio.h> #include <stdio.h> #define SIZE 10 void main() { int A; int B; int *p; int **pp; A = 10; B = 111; p = &A; pp = &p; printf(«A = %d\n», A); *p = 20; printf(«A = %d\n», A); *(*pp) = 30; //здесь скобки можно не писать printf(«A = %d\n», A); *pp = &B; printf(«B = %d\n», *p); **pp = 333; printf(«B = %d», B); getch(); }

Указатели и приведение типов

Так как указатель хранит адрес, можно кастовать его до другого типа.

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

#include <conio.h> #include <stdio.h> #define SIZE 10 void main() { int A = 10; int *intPtr; char *charPtr; intPtr = &A; printf(«%d\n», *intPtr); printf(«———————\n»); charPtr = (char*)intPtr; printf(«%d «, *charPtr); charPtr++; printf(«%d «, *charPtr); charPtr++; printf(«%d «, *charPtr); charPtr++; printf(«%d «, *charPtr); getch(); }

В этом примере мы пользуемся тем, что размер типа int равен 4 байта, а char 1 байт. За счёт этого, получив адрес первого байта, можно пройти по остальным байтам числа и вывести их содержимое.

NULL pointer — нулевой указатель

Указатель до инициализации хранит мусор, как и любая другая переменная. Но в то же время, этот «мусор» вполне может оказаться валидным адресом. Пусть, к примеру, у нас есть указатель. Каким образом узнать, инициализирован он или нет? В общем случае никак. Для решения этой проблемы был введён макрос NULL библиотеки stdlib.
Принято при определении указателя, если он не инициализируется конкретным значением, делать его равным NULL.

int *ptr = NULL;

По стандарту гарантировано, что в этом случае указатель равен NULL, и равен нулю, и может быть использован как булево значение false. Хотя в зависимости от реализации NULL может и не быть равным 0 (в смысле, не равен нулю в побитовом представлении, как например, int или float).
Это значит, что в данном случае

int *ptr = NULL; if (ptr == 0) { … }

вполне корректная операция, а в случае

int a = 0; if (a == NULL) { … }

поведение не определено. То есть указатель можно сравнивать с нулём, или с NULL, но нельзя NULL сравнивать с переменной целого типа или типа с плавающей точкой.

#include <stdlib.h> #include <stdio.h> #include <conio.h> void main() { int *a = NULL; unsigned length, i; printf(«Enter length of array: «); scanf(«%d», &length); if (length > 0) { //При выделении памяти возвращается указатель. //Если память не была выделена, то возвращается NULL if ((a = (int*) malloc(length * sizeof(int))) != NULL) { for (i = 0; i < length; i++) { a[i] = i * i; } } else { printf(«Error: can’t allocate memory»); } } //Если переменая была инициализирована, то очищаем её if (a != NULL) { free(a); } getch(); }

Примеры

Теперь несколько примеров работы с указателями
1. Пройдём по массиву и найдём все чётные элементы.

#include <conio.h> #include <stdio.h> void main() { int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int even[10]; int evenCounter = 0; int *iter, *end; //iter хранит адрес первого элемента массива //end хранит адрес следующего за последним «элемента» массива for (iter = A, end = &A[10]; iter < end; iter++) { if (*iter % 2 == 0) { even[evenCounter++] = *iter; } } //Выводим задом наперёд чётные числа for (—evenCounter; evenCounter >= 0; evenCounter—) { printf(«%d «, even[evenCounter]); } getch(); }

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

#include <conio.h> #include <stdio.h> #define SIZE 10 void main() { double unsorted[SIZE] = {1.0, 3.0, 2.0, 4.0, 5.0, 6.0, 8.0, 7.0, 9.0, 0.0}; double *p[SIZE]; double *tmp; char flag = 1; unsigned i; printf(«unsorted array\n»); for (i = 0; i < SIZE; i++) { printf(«%.2f «, unsorted[i]); } printf(«\n»); //Сохраняем в массив p адреса элементов for (i = 0; i < SIZE; i++) { p[i] = &unsorted[i]; } do { flag = 0; for (i = 1; i<SIZE; i++) { //Сравниваем СОДЕРЖИМОЕ if (*p[i] < *p[i-1]) { //обмениваем местами АДРЕСА tmp = p[i]; p[i] = p[i-1]; p[i-1] = tmp; flag = 1; } } } while(flag); printf(«sorted array of pointers\n»); for (i = 0; i < SIZE; i++) { printf(«%.2f «, *p[i]); } printf(«\n»); printf(«make sure that unsorted array wasn’t modified\n»); for (i = 0; i < SIZE; i++) { printf(«%.2f «, unsorted[i]); } getch(); }

3. Более интересный пример. Так как размер типа char всегда равен 1 байт, то с его помощью можно реализовать операцию swap – обмена местами содержимого двух переменных.

#include <conio.h> #include <conio.h> #include <stdio.h> void main() { int length; char *p1, *p2; char tmp; float a = 5.0f; float b = 3.0f; printf(«a = %.3f\n», a); printf(«b = %.3f\n», b); p1 = (char*) &a; p2 = (char*) &b; //Узнаём сколько байт перемещать length = sizeof(float); while (length—) { //Обмениваем местами содержимое переменных побайтно tmp = *p1; *p1 = *p2; *p2 = tmp; //не забываем перемещаться вперёд p1++; p2++; } printf(«a = %.3f\n», a); printf(«b = %.3f\n», b); getch(); }

В этом примере можно поменять тип переменных a и b на double или любой другой (с соответствующим изменением вывода и вызова sizeof), всё равно мы будет обменивать местами байты двух переменных.

4. Найдём длину строки, введённой пользователем, используя указатель #include <conio.h> #include <stdio.h> void main() { char buffer[128]; char *p; unsigned length = 0; scanf(«%127s», buffer); p = buffer; while (*p != ‘\0’) { p++; length++; } printf(«length = %d», length); getch(); }

Обратите внимание на участок кода

while (*p != ‘\0’) { p++; length++; }

его можно переписать

while (*p != 0) { p++; length++; } или while (*p) { p++; length++; }

или, убрав инкремент в условие

while (*p++) { length++; }

ru-Cyrl18-tutorialSypachev S.S.1989-04-14sypachev_s_s@mail.ruStepanSypachevstudents

Q&A

Указатель — это специальная переменная, которая хранит адрес другой переменной. Указатель объявляется следующим образом: тип* переменная; где тип — любой допустимый как простой, так и составной базовый тип указателя.

Например, пусть объявлена обычная переменная int t; Объявление и инициализация int* p= &t; означают следующее. В переменной p будетхраниться не обрабатываемое программой целое число (оценка студента, количество выпущенной продукции и т. п.), а адрес ячейки, в которой будет находиться информация указанного типа (целое число). Под адресом будем понимать номер первого байта выделенного для переменной участка оперативной памяти. Для переменных, не являющихся указателями, без дополнительного объявления адрес также запоминается системой, и его можно получить с помощью операции & (разадресации), например, &t. Эта унарная операция, которую иногда называют “взятие адреса”, ничего не делает со значением переменной t.

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

Один из способов показан выше и означает, что в переменную p помещается адрес ячейки t. Важно понять, что int* p= &t; равносильно int* p; p=&t ; а не *p=&t; В этом заключается одна из трудностей начального этапа изучения указателей. Эта тема усложняется ещё и тем, что такой же символ “&” используется при объявлении переменной ссылочного типа.

Указатели в Си.

Здесь этот символ определяет операцию взятия адреса для переменной и никакого отношения к ссылочному типу не имеет.

Заметим, что расстановка пробелов при объявлении указателей свободная. Допустимы также следующие записи: int * p= & t; int *p= &t; Предпочтение следовало бы отдать записи в начале параграфа, из которой легче понять смысл указателя. Объявляется переменная p, а не *p, и, кроме этого, типом является int*, а не int.

Если одновременно объявляется несколько указателей, то символ “*” надо писать перед каждой переменной: float* q1, *q2;

Содержимое ячейки, адрес которой находится в p, в тексте программы обозначается с помощью операции разыменование. Для неё используется тот же символ “*”, что и при объявлении переменной-указателя. Эта унарная операция возвращает значение переменной, находящейся по указанному адресу. Поэтому *p — это обрабатываемое программой целое число, находящееся в ячейке, адрес которой — в переменной-указателе p. С учётом инициализации (p = &t) *p и t — это одно и то же значение. Значит, если с помощью cin>>t; введём, например, число 2 и выполним *p*=5; или *p=*p*5; то изменится и величина t, хотя, казалось бы, не было явного её изменения. Поэтому оператор cout << t; выведет число 10 (2*5). И наоборот, изменив t (например, t++;), этим самым мы изменим и значение *p. С помощью cout<<(*p); выведем 11.

Сказанное выше будем обозначать так:

p (или &t) *p (или t)

В “левом прямоугольнике” (ячейке памяти) находится адрес, а в ячейке “справа” — обрабатываемое целое число.

Рассматриваемые здесь операции “&” и ”*” являются унарными и имеют более высокий приоритет по сравнению с аналогичными бинарными операциями “битовое и” и арифметическое умножение.

Для *p определены те же операции, что и для переменной указанного типа, у нас — для целых чисел. Поэтому допустимы, например, следующие операторы: а) cin>>(*p); b) int r; r=*p*2; c) if (*p%2)…; d) cout<<(*p);.

Можно выводить и значение переменной-указателя. cout<<p; выведет адрес в шестнадцатеричной системе счисления. При этом он не обязательно будет одинаковым при повторном выполнении одной и той же программы.


⇐ Предыдущая567891011121314Следующая ⇒


Дата публикования: 2015-02-18; Прочитано: 526 | Нарушение авторского права страницы



studopedia.org — Студопедия.Орг — 2014-2018 год.(0.001 с)…

.

— указатель на Работника. Вы можете назначить один выделенный объект этому указателю или, в вашем случае, несколько ( с синтаксисом массива). Таким образом, он указывает на массив сотрудников.

Вы разыменовали этот указатель.

Обозначения и предположения

Поскольку он указывает на массив (нескольких) сотрудников, он также указывает на первую запись. Затем вы получаете доступ к целочисленной переменной-члену, которая по-прежнему возможна. Но затем вы пытаетесь использовать оператор индекса массива () для целочисленного значения, что невозможно.

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

в словах низкого уровня означает: возьмите указатель , добавьте раз размер указанного типа (чтобы он указывал на -ную запись) и разыменовал этот адрес, Это означает, что фактически является Employee в -ом индексе (но не в указателе).

Затем вы хотите получить доступ к члену этого сотрудника.

Если он все еще был указателем, вам нужно будет использовать оператор стрелки, но поскольку вы использовали оператор индекса массива (), вы уже разыменовали его, то оператор точки правильный:

ответ дан leemes 18 апр. '13 в 22:25

источникподелиться

FILED UNDER : IT

Submit a Comment

Must be required * marked fields.

:*
:*