#c #list #file #pointers
Вопрос:
Если я объявил указатель p
как int *p
; в главном модуле, я могу изменить содержащийся в нем адрес p
, назначив p = amp;a;
, где a
уже объявлена другая целочисленная переменная. Теперь я хочу изменить адрес, используя функцию как:
void change_adrs(int*q)
{
int *newad;
q = newad;
}
Если я вызову эту функцию из основного модуля
int main()
{
int *p;
int a = 0;
p = amp;a; // this changes the address contained by pointer p
printf("The address is %un", p);
change_adrs(p);
printf("The address is %un", p); // but this doesn't change the address
return 0;
}
содержимое адреса не изменилось. Что плохого в использовании функции для одной и той же задачи?
Комментарии:
1. Вы передаете указатель по значению. Если вам нужно изменить указатель внутри функции, передайте его по ссылке… двойной указатель.
Ответ №1:
В C аргументы функций передаются по значению. Таким образом, создается копия вашего аргумента, и изменение вносится в эту копию, а не в фактический объект указателя, который вы ожидаете увидеть измененным. Вам нужно будет изменить свою функцию, чтобы принять аргумент от указателя к указателю и внести изменения в разыменованный аргумент, если вы хотите это сделать. Например
void foo(int** p) {
*p = NULL; /* set pointer to null */
}
void foo2(int* p) {
p = NULL; /* makes copy of p and copy is set to null*/
}
int main() {
int* k;
foo2(k); /* k unchanged */
foo(amp;k); /* NOW k == NULL */
}
Если у вас есть роскошь использовать C , альтернативным способом было бы изменить функцию, чтобы она принимала ссылку на указатель.
Комментарии:
1. Я просто хотел бы отметить, что стандарт C не гарантирует, что присвоение p 0 делает его нулевым.
2. Если бы я указал на
*arr = malloc()
новый массив в вызываемой функции и указал**p
на него, так ли это*p = amp;arr
?3. @JKRT: 6.2.3.2 в спецификации C говорится, что «Целочисленное постоянное выражение со значением 0 или такое выражение, приведенное к типу void*, называется константой указателя null». — поэтому назначение литерала 0 сделает его нулевым. «Или» в этом предложении означает, что приведение не требуется.
Ответ №2:
В C переменные передаются по значению — копия указателя передается функции. Вместо этого используйте другой указатель на указатель:
void change(int **p, int *someOtherAddress)
{
*p = someOtherAddress;
}
int a = 1, b = 2;
int *p = amp;a;
printf("*p = %dn", *p);
change(amp;p, amp;b);
printf("*p = %dn", *p);
Это печатает
*p = 1
*p = 2
Комментарии:
1. Поднимите голос исключительно потому, что этот ответ позволяет избежать фразы «двойной указатель».
Ответ №3:
Если вы хотите изменить содержимое переменной в функции на языке Си, указатель также является своего рода переменной, вы должны передать его по указателю или косвенной ссылке, используя операторы всегда amp;
адреса и *
разыменования. Я имею *
в виду, что оператор всегда используется и предшествует при изменении значения переменной.
#include <stdio.h>
#include <stdlib.h>
void changeIntVal(int *x) {
*x = 5;
}
void changePointerAddr(int **q) {
int *newad;
*q = newad;
}
void changePPAddr(int ***q) {
int **dummy;
*q = dummy;
}
int main() {
int *p;
int **pp;
int *tempForPP;
int a = 0;
printf("n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
p = amp;a;
pp = amp;tempForPP;
printf("n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
changeIntVal(amp;a); // ----
// |---
changePointerAddr(amp;p); // ---- |----> parts of what I mean
// |---
changePPAddr(amp;pp); // ----
printf("n The address pointing by p -> %p, pp -> %p, value of a -> %d ", p, pp, a);
return 0;
}
Ответ №4:
Для примитивного типа данных , такого как an int
, двойные указатели не нужны. Вы можете записать непосредственно в адрес, где int
хранится, обрабатывая его адрес как указатель в вызываемой функции. Это не похоже на char
массив («строка»), где размер того, на что указано, является переменным, и поэтому вы должны использовать другой уровень косвенности при изменении его внутри вызываемой функции. Попробуйте это:
void foo(int *oldVal)
{
int newVal = 99; // or whatever you want
*oldVal = newVal;
}
int main(int argc, char *argv[])
{
int someVal = 0;
foo(amp;someVal); // we send its address to foo()
printf("someVal is now %d.n", someVal);
return EXIT_SUCCESS;
}
Комментарии:
1. Это не ответ на вопрос !, он просит изменить адрес указателя, а не значение указателя
Ответ №5:
Это не изменит фактическое значение p
, потому q
что функция in локальна для этого, и изменение в этой функции не отразится, main
поэтому передайте адрес p
вместо передачи p
по значению
Используйте этот синтаксис ниже
void change_adrs(int **q)
{
int * otheraddess;
*q = otheraddress;
}
и позвонить вот так change_adrs(amp;p);
Или у вас есть другой способ: измените тип возвращаемой функции и поймайте возвращаемый адрес.
int* change_adrs(int *q)
{
int * otheraddess;
q = otheraddress;
return q;
}
int main()
{
p = change_adrs(p);
return 0;
}