Я изо всех сил пытаюсь визуализировать указатели на переменные, в соответствии с K & R - PullRequest
0 голосов
/ 09 февраля 2019

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

Рассмотрим пример 1 после компиляции этого кода с помощью cc t2.c,и его выполнение, похоже, не работает должным образом, адреса px и py не переставляются по какой-либо причине.

Пример 1:

#include <stdio.h>

void swap(int *,int *);

int main(){
    int x=3;
    int y=2;
    int *px;
    int *py;
    px=&x;
    py=&y;

    printf("px = %x\npy = %x\n",&px,&py);
    swap(px,py);
    printf("After the swap\npx = %x\npy = %x\n",&px,&py);
}

void swap(int *px,int *py){
    int temp;
    temp=*px;
    *px=*py;
    *py=temp;
}

GDB из примера 1:

6                       int x=3;
(gdb) n
7                       int y=2;
(gdb) n
10                      px=&x;
(gdb) p x
$1 = 3
(gdb) p &x
$2 = (int *) 0x7efff5cc
(gdb) p px
$3 = (int *) 0x0
(gdb) p &px
$4 = (int **) 0x7efff5d4
(gdb) n
11                      py=&y;
(gdb) p px
$5 = (int *) 0x7efff5cc
(gdb) p &px
$6 = (int **) 0x7efff5d4

....

pi@readonly:~/new$ cc t2.c
pi@readonly:~/new$ a.out
px = 7ea765fc
py = 7ea765f8
After the swap
px = 7ea765fc
py = 7ea765f8

Пример 2:

int x = 1, y = 2 ;int *ip;  /* ip is a pointer to an int */
ip = &x;  /* ip now points to x */
y = *ip;  /* y is now 1 */
*ip = 10; /* x is now 10 */
*ip = *ip + 1; /* x is now 11 */
*ip += 1; /* x is now 12 */
++*ip;   /* x is now 13 */
(*ip)++; /* x is now 14, parentheses are required */

Пример 1 Q:

1) Правильно ли я понимаю, что, начиная с $5, px - это точно такая же переменная, как x, за исключением того, что ее значение установлено в 0x7efff5cc в шестнадцатеричном формате, который является просто адресом переменнойx в памяти ??

2) Если мы используем объявление int *ip, значит ли это, что переменная ip имеет значение, равное адресу int?Тогда каков адрес int в шестнадцатеричном формате?

3) Что означает адрес переменной, что это за 0x7efff5cc?Другими словами:

  • Я знаю, что есть RAM, L2, L3, L1 кэши CPU, ROM.Итак, адрес какой конкретной памяти представляет это число?

  • Сколько таких 0x7efff5cc может вместить этот конкретный тип памяти?Или, где я могу проверить это в системе Linux?

4) Что означает запись (int **)?

5) Что не так с программой, как исправитьэто для того, чтобы адреса px и py были заменены после передачи в качестве значений аргумента функции swap?

Пример 2 Q:

5) Относительнонотации, я правильно понимаю, что как только мы объявим, что переменная ip является указателем на int, через int *ip, мы не можем присвоить, например, десятичное значение для ip, позжеon, используя присваивание, подобное: ip = 10;, поскольку после того, как переменная была объявлена ​​как указатель, она используется исключительно для хранения адресов других переменных, на которые ip "указывает", в шестнадцатеричном формате?

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Ваша функция swap обменивается значениями x и y, а не значениями px и py.

Поскольку px == &x, это означает *px == x,То же самое верно для py.

Чтобы функция записала новое значение в параметр, необходимо передать указатель на параметр:

void foo( T *ptr )
{
  *ptr = new_value();  // write a new value to the thing ptr points to
}

void bar( void )
{
  T var; // for any non-array type T

  foo( &var ); // write a new value to var
  ...
}

Это верно для любого не- тип массива T, , включая типы указателей .Давайте заменим T типом указателя P *, поэтому код теперь

void foo( P **ptr )
{
  *ptr = new_value();  // write a new value to the thing ptr points to
}

void bar( void )
{
  P *var;

  foo( &var ); // write a new value to var
  ...
}

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

Поэтому, если вы хотите, чтобы ваша функция меняла значения px и py, она должна быть записана как

void swap( int **ppx, int **ppy )
{
  int *tmp = *ppx; // int * = int *
  *ppx = *ppy;     // int * = int *
  *ppy = tmp;      // int * = int *
}

и называется как

px = &x;
py = &y;
swap( &px, &py );
0 голосов
/ 09 февраля 2019

Пример 1 Q:

1) Правильно ли я понимаю, что, начиная с $ 5, px - это точно та же переменная, что и x, за исключением того, что ее значение установлено в 0x7efff5cc в шестнадцатеричном формате, который является просто адресом переменной x в памяти ??

px - переменная-указатель.Это означает, что px - это переменная, которая содержит адрес.Вы присвоили его адресу x с помощью px = & x, но вы можете присвоить ему любое значение.

2) Если мы используем объявление int * ip, означает ли это, что переменная ip имеет значение, равное адресу int?Тогда, каков адрес int в шестнадцатеричном формате?

int * p - переменная-указатель, которая указывает на int.https://cdecl.org/?q=int+*ip%3B

3) Что означает адрес переменной, что это за 0x7efff5cc?Другими словами:

Я знаю, что есть RAM, L2, L3, L1 кэши CPU, ROM.Итак, адрес какой конкретной памяти представляет это число?

0x7efff5cc - это виртуальный адрес , который ОС предоставила пространству данных в вашей программе для хранения int x;

Сколько таких 0x7efff5cc может содержать этот конкретный тип памяти?

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

Или, где я могу проверить это в системе Linux?

см. это для получения информации о том, как узнать, что физический адрес для виртуального адреса наlinux: Существует ли какой-либо API для определения физического адреса по виртуальному адресу в Linux?

4) Что означает запись (int **)?

переменная является указателем на указатель на int.

5) Что не так с программой, как ее исправить, чтобы после замены адреса px и py менялисьпередано в качестве аргумента вауказывает на функцию swap?

исправлены проблемы в вашей программе подкачки:

#include <stdio.h>

void swap( int **, int ** );

int main()
    {
    int x = 3;
    int y = 2;
    int *px;
    int *py;
    px = &x;
    py = &y;

    printf( "px = %x\npy = %x\n", px, py );
    swap( &px, &py );
    printf( "After the swap\npx = %x\npy = %x\n", px, py );

    }

void swap( int **px, int **py )
    {
    int *temp;
    temp = *px;
    *px = *py;
    *py = temp;
    }

Пример 2 Q:

5) Что касается записи,Правильно ли я понимаю, что как только мы объявим, что переменная ip является указателем на int, через int * ip мы не сможем присвоить, например, десятичное значение ip, позже, используя присваивание, например: ip = 10;поскольку после того, как переменная была объявлена ​​как указатель, она используется исключительно для хранения адресов других переменных, на которые ip «указывает», в шестнадцатеричном виде?

нет, вы можете изменить то, что ipуказывает на.

int *ip;
ip = &x; 
ip = &y;
ip++;
...