Вопрос

Из конспектов лекций университетского курса по «вызову по значению»:

void fun(int *ip)

{

*ip =100;

}

позвонил

int n=2;  

int *np;

np = &n; 

fun(np);

изменит значение n на 100.

Когда мы говорим «int *ip», что именно мы имеем в виду?Указатель целочисленного типа?Если да, то когда мы вызываем fun() с аргументом np, не должна ли возникнуть ошибка, поскольку np имеет адрес n, который не является целым числом?

А затем мы меняем значение ip на 100, не означает ли это, что n теперь имеет значение, которое находится в «слоте памяти» с адресом 100?Я уверен, что что-то упускаю.:)

Это было полезно?

Решение

Указатель целочисленного типа?

Нет, указатель к целое число.

когда мы вызываем fun() с аргументом np, не должна ли возникнуть ошибка, поскольку np имеет адрес n, который не является целым числом?

n является целым числом, поэтому проблем нет. &n, np и ip все они имеют один и тот же тип в вашем коде: int*.

А затем меняем значение ip на 100

Нет… мы меняем значение *ip, не из ip.То есть мы меняем значение, которое ip указывает на (которое также иногда называют пуант).

Другие советы

Да, когда вы используете int * как тип параметра fun вы говорите, что он принимает указатель на int.С np это указатель на int, передающий его в fun все в порядке.

np и ip указывают на адрес n, поэтому, когда вы присваиваете значение типа *ip = 42, он присвоит значение 42 ячейке памяти, которая ip указывает на - что n.

То, что у вас есть в примере кода, называется пройти по указателю.Ваша функция имеет параметр типа указатель на целое число.Таким образом, значение, передаваемое в функцию, равно адрес переменной n.Функция назначает 100 к переменной (т.е.место памяти) указал на по параметру указателя ip.Звезда * это оператор разыменования на С/С++.

в fun() вы не меняете значение ip на 100, вы меняете место в памяти, на которое указывает ip.

type* использование в качестве типа означает «указатель на этот тип»

общее использование - это int *var, но мне нравится писать это как int* var поскольку это делает его лучшим отличием от разыменования указателя, т.е. *ptr.

так int* a означает, что a является указателем на объект типа int, *a означает объект, на который указывают и &a означает адрес объекта a.

думать о np по типу int*.Имейте в виду, что для этого звездочка и int вместе образуют тип «указатель на int» и не являются разделяемыми.

ip это указатель, с ip* вы получаете доступ к «слоту памяти», на который он указывает. np также является указателем.С использованием &n вы назначаете адрес слота памяти n к np.Поэтому при звонке fun(), внутри fun() единственный доступный слот памяти - это один из n и таким образом n назначено 100.

Здесь возможна некоторая путаница, поскольку и n, и np хранят числа — однако при компиляции компилятор будет использовать числа по-разному;то есть, пока

n++;

и

np++;

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

Конкретно по вашему примеру.

*np = 100;

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

(* (np) ) = 100;

или в другом контексте:

int n = *np;

Теперь, должен сказать, мое сердце согревается, когда вы говорите:

мы меняем значение ip на 100, не означает ли это, что n теперь имеет значение, которое находится в «слоте памяти» с адресом 100?поскольку это противоречит тому, что я считаю важным пониманием.Однако я считаю, что прав, когда говорю, что вы должны изо всех сил стараться делать такие вещи с указателями:

static_cast<int>(np) = 100;

Это будет делать то, что вы описали, потому что это говорит компьютеру рассматривать число np как число другого типа;таким же образом, что static_cast<char*>(np) будет рассматривать число, на которое указывает np, как символ, а не как целое число.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top