Передача указателя в функцию C ++ (Howto) + манипуляция указателем в C ++ - PullRequest
24 голосов
/ 26 сентября 2010

Я немного смущен тем, как работает передача указателей.

Допустим, у меня есть следующая функция и указатель, и ...

РЕДАКТИРОВАТЬ :

... Я хочу использовать указатель на некоторый объект в качестве аргумента в функции.

т.е:.

void Fun(int Pointer){
    int Fun_Ptr = ---Passed Pointer---; 
    //So that Fun_Ptr points to whatever ---Passed Pointer points to

Между нотациями * Pointer и & Pointer я очень запутался. Я знаю, что * Указатель означает дать все, на что он указывает.

Нужно ли указывать void (int * pointer) в объявлении. Как насчет того, когда я использую функцию?

Ваша помощь приветствуется.

РЕДАКТИРОВАТЬ 2:

Хорошо, теперь я понимаю, что использование * переменной в объявлении означает, что указатель будет передан. Однако что делать, когда я использую функцию?

* * +1025 т.е. * * 1 026
int main(){
    int foo;
    int *bar;
    bar = foo;
    Fun(bar);
}

РЕДАКТИРОВАТЬ 3: Хорошо, поправьте меня, если я ошибаюсь:

В соответствии с соглашениями приведенного выше кода:

bar = & foo означает: сделать бар указателем на foo в памяти

* bar = foo означает изменить значение, на которое указывает bar, на любое равное foo

Если у меня есть второй указатель (int * oof), то:

bar = oof означает: бар указывает на указатель oof

bar = * oof означает: bar указывает на значение, на которое указывает oof, но не на сам указатель oof

* bar = * oof означает: измените значение, на которое указывает bar, на значение, на которое указывает oof, на

& bar = & oof означает: изменить адрес памяти, на который указывает строка, таким же, как адрес памяти, на который указывает oof,

Имею ли я это право?

РЕДАКТИРОВАТЬ 4: Большое спасибо за вашу помощь (хотелось бы принять более одного ответа, но я должен идти с первым. Я не уверен, как вики сообщества работает точно, но я оставлю этот способ для редактирования (не стесняйтесь превратить его в справочник, если хотите).

Ответы [ 7 ]

45 голосов
/ 26 сентября 2010

Существует разница в использовании * при определении переменной и при ее использовании.

В объявлении

int *myVariable;

Означает указатель на целочисленный тип данных,При использовании, однако,

*myVariable = 3;

Означает разыменование указателя и делает структуру, на которую он указывает, равной трем, вместо того, чтобы сделать указатель равным адресу памяти 0x 0003.

Так что вваша функция, вы хотите сделать это:

void makePointerEqualSomething(int* pInteger)
{
    *pInteger = 7;
}

В объявлении функции * означает, что вы передаете указатель, но в его фактическом теле кода * означает, что вы получаете доступ к тому, на что указывает указатель.

В попытке избавиться от любой путаницы, которую вы испытываете, я кратко зайду в амперсанд (&)

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

 int & myVariable;

В объявлении подразумевается адрес целого числа или указателя!

Это однако

int someData;    
pInteger = &someData;

Означает, что сам указатель pInteger (помните, указатели)это просто адреса памяти того, на что они указывают), равные адресу 'someData' - так что теперь pInteger будет указывать на некоторые данные и может использоваться для доступа к ним, когда вы обращаетесь к ним:

*pInteger += 9000;

Doeэто имеет смысл для вас?Есть ли что-то еще, что вас смущает?

@ Edit3:

Почти правильно, за исключением трех операторов

bar = *oof;

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

&bar = &oof;

Амперсанд подобен функции, как только он возвращает адрес памяти, вы не можете изменить, откуда он пришел.Точно так же, как этот код:

returnThisInt("72") = 86; 

Недопустим, как и ваш.

Наконец,

bar = oof

Не означает, что "бар указывает на указатель на oof."Скорее, это означает, что bar указывает на адрес, на который указывает oof, поэтому bar указывает на то, на что указывает foo, а не bar указывает на foo, который указывает на oof.

15 голосов
/ 26 сентября 2010

Чтобы объявить функцию, которая принимает указатель на int:

void Foo(int *x);

Чтобы использовать эту функцию:


int x = 4;
int *x_ptr = &x;
Foo(x_ptr);
Foo(&x);

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

void Foo(Object *o);

Но вы можете предпочесть использовать ссылки. Они несколько менее запутаны, чем указатели:


// pass a reference
void Foo(int &x)
{
  x = 2;
}

//pass a pointer
void Foo_p(int *p)
{
   *x = 9;
}

// pass by value
void Bar(int x)
{
   x = 7;
}
int x = 4;
Foo(x);  // x now equals 2.
Foo_p(&x); // x now equals 9.
Bar(x);  // x still equals 9.

Со ссылками вы все равно можете изменить x, который был передан функции (как с указателем), но вам не нужно беспокоиться о разыменовании или адресе операций.

В соответствии с рекомендациями других, ознакомьтесь с C ++ FAQLite . Это отличный ресурс для этого.

Редактировать 3 ответа:

bar = & foo означает: сделать так, чтобы bar указывал на foo в памяти

Да.

* bar = foo означает изменить значение, на которое указывает bar, на любое равное foo

Да.

Если у меня есть второй указатель (int * oof), то:

bar = oof означает: бар указывает на указатель oof

Бар

будет указывать на то, на что указывает oof. Они оба будут указывать на одно и то же.

bar = * oof означает: bar указывает на значение, на которое указывает oof, но не на сам указатель oof

Нет. Вы не можете сделать это (при условии, что bar имеет тип int *). Вы можете создавать указатели указателей. (int **), но давайте не будем вдаваться в это ... Вы не можете назначить указатель на int (ну, вы можете, но это деталь, которая не соответствует обсуждению). * bar = * oof означает: изменить значение, на которое указывает bar, на значение, на которое указывает oof, на

Да.

& bar = & oof означает: изменить адрес памяти, на который указывает строка, таким же, как адрес памяти, на который указывает oof, на

Нет. Вы не можете сделать это, потому что адрес оператора возвращает значение r. По сути, это означает, что вы не можете назначить ему что-либо.

3 голосов
/ 26 сентября 2010

Если вы хотите передать указатель на int в вашу функцию,

Декларация функции (если она вам нужна):

void Fun(int *ptr);

Определение функции:

void Fun(int *ptr) {
    int *other_pointer = ptr;  // other_pointer points to the same thing as ptr
    *other_ptr = 3;            // manipulate the thing they both point to
}

Использование функции:

int main() {
    int x = 2;
    printf("%d\n", x);
    Fun(&x);
    printf("%d\n", x);
}

Обратите внимание, как правило, что переменные, называемые Ptr или Pointer, никогда не должны иметь тип int, который у вас есть в вашем коде. Указатель на int имеет тип int *.

Если у меня есть второй указатель (int * oof), то:

bar = oof означает: бар указывает на oof указатель

Это означает, что «сделать планку одинаковой, на другую указывает».

bar = * oof означает: бар указывает на значение, на которое указывает oof, но не на сам указатель на

Это ничего не значит, это недействительно. bar это указатель *oof это int. Вы не можете назначить одно другому.

* bar = * oof означает: изменить значение, на которое указывает bar, на значение, которое oof указывает на

Да.

& bar = & oof означает: изменить память адрес этой точки указывает на то же самое в качестве адреса памяти, который указывает до

Нет, это снова недействительно. &bar - указатель на переменную bar, но это то, что называется «rvalue» или «временным», и его нельзя назначить. Это как результат арифметического расчета. Вы не можете написать x + 1 = 5.

Это может помочь вам думать об указателях как об адресах. bar = oof означает «make bar, который является адресом, равным oof, который также является адресом». bar = &foo означает «make bar, который является адресом, равным адресу foo». Если bar = *oof означает что-либо, это будет означать «make bar, который является адресом, равным *oof, который является целым». Вы не можете.

Тогда & является адресом оператора. Это означает «адрес операнда», поэтому &foo - это адрес foo (то есть указатель на foo). * является оператором разыменования. Это означает «вещь по адресу, указанному операндом». Итак, сделав bar = &foo, *bar - это foo.

3 голосов
/ 26 сентября 2010

Для передачи указателя на int это должно быть void Fun(int* pointer).

Передача ссылки на int будет выглядеть следующим образом ...

void Fun(int& ref) {
   ref = 10;
}

int main() {
   int test = 5;
   cout << test << endl;  // prints 5

   Fun(test);
   cout << test << endl;  // prints 10 because Fun modified the value

   return 1;
}
1 голос
/ 26 сентября 2010
void Fun(int* Pointer)   -- would be called as Fun( &somevariable )

позволит вам манипулировать содержимым того, на что указывает «Указатель», путем разыменования его внутри функции Fun, т. Е.

*Pointer = 1;

, объявив его, как указано выше, также позволяет вам манипулировать данными помимо того, чтоон указывает на:

int foo[10] = {0};
Fun(foo);

в функции, которую вы затем можете сделать, например * (Pointer + 1) = 12;установив второе значение массива.

void Fun(int& Pointer)  -- would be called Fun( somevariable )

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

1 голос
/ 26 сентября 2010
void Fun(int *Pointer)
{
  //if you want to manipulate the content of the pointer:
  *Pointer=10;
  //Here we are changing the contents of Pointer to 10
}

* перед указателем означает содержимое указателя (кроме объявлений!)

& перед указателем (или любой переменной) означает адрес

EDIT:

int someint=15;
//to call the function
Fun(&someint);
//or we can also do
int *ptr;
ptr=&someint;
Fun(ptr);
0 голосов
/ 26 сентября 2010

Возможно, вам будет легче понять, используя функционально более выразительные и мощные функциональные возможности, см. Этот превосходный и настоятельно рекомендуемый C ++ FAQ lite , в частности, смотрите раздел 33.12, но тем не менее Прочитайте его в начале этого раздела, чтобы понять и понять его.

Чтобы ответить на ваш вопрос:

typedef void (*foobar)() fubarfn;

void Fun(fubarfn& baz){
   fubarfn = baz;
   baz();
}

Edit:

  • & означает адрес ссылки
  • * означает значение того, что содержится по адресу ссылки, называемому разыменование

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

void FunByRef(int& iPtr){
    iPtr = 2;
}

int main(void){
    // ...
    int n;
    FunByRef(n);
    cout << n << endl; // n will have value of 2
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...