Может кто-нибудь объяснить логическую ошибку в этой программе? - PullRequest
1 голос
/ 12 июля 2020
#include <stdio.h>

int main() {
    int a = 5, *p, **q, b;
    p = &a;
    q = p;
    b = *q;
    printf("%d", b);
}

Я хочу выяснить, как эти назначения ошибочны на уровне памяти. Предположим, адрес a - 100. p = &a - правильное присвоение. Тогда p будет указывать на адрес 100. Меня смущают утверждения q = p и b = *q. Как они ошибаются?

Ответы [ 3 ]

3 голосов
/ 12 июля 2020

p = &a; правильно. - Назначение адреса a указателю p.

q = p; неверно (конфликт типов). - Вы пытаетесь назначить указатель (*) указателю на указатель (**). Он должен быть q = &p, чтобы вы получили адрес p и назначили его указателю на указатель q.

b = *q; неверно (конфликт типов). - Вы пытаетесь назначить указатель (*q прирост p) объекту int. Это должно быть b = **q;, чтобы присвоить значение a b.

Если бы вы скомпилировали этот код с помощью современного компилятора, совместимого со стандартами, он бы показал вам все конфликты и, вероятно, ответил бы на большинство ваших вопросов.

В следующий раз перед публикацией попробуйте выполнить свой код с помощью компилятора, такого как G CC или Clang, и посмотрите, что он сообщает вам с помощью c сообщений диагностики.

Если вы не хотите устанавливать пакет компилятора или IDE на свой компьютер, хотя и настоятельно рекомендуется, вы можете скомпилировать его онлайн с помощью Godbolt или OnlineGDB .

Компилятор - ваш лучший друг в поиске синтаксических проблем c. Особенно, если вы используете еще больше вспомогательных флагов, таких как -Wall, -Wextra и -Werror. : -)

2 голосов
/ 12 июля 2020
#include<stdio.h>
int main()
{
   int a=5,*p,**q,b;    #1
   p=&a;                #2
   q=p;                 #3
   b=*q;                #4
   printf("%d",b);      #5
}
  1. в # 1 , вы объявили целочисленный тип данных a и инициализировали его значением 5. Предположим, что его адрес в памяти - 0x100. p является целочисленным указателем и не инициализирован (некоторые (не все) компиляторы сегодня имеют его как функцию и инициализируют его как NULL, , но вы не должны полагаться на это, и вы должны явно инициализировать его значением NULL! ), q - указатель на целочисленный указатель и неинициализированный (тот же комментарий, что и раньше), b - неинициализированное целое число.
  2. in # 2 , вы назначаете адрес a p, поэтому теперь p указывает на a в памяти. Следовательно, значение p: 0x100
  3. in # 3 , вы назначаете p (который является int указателем) на указатель на указатель int ! это неправильно, но компилятор пропустит вас с предупреждением: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]. Исправление для этого warning: q=&p;. поскольку это всего лишь предупреждение, q указывает на 0x100!
  4. b является целым числом, вы назначаете ему *q, что является значением q, то есть 0x100 в этом случае (вы не можете присвоить адрес памяти переменной int), и он имеет тип int pointer! Опять же, это неверно, но компилятор пропустит вас с предупреждением: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]. Вам следует сделать b = **q. Теперь значение b: (*q), что равно *(&p), что равно *(0x100), что составляет 5!
  5. печатает значение b, следовательно, печатает 5
2 голосов
/ 12 июля 2020

q имеет тип int** - это указатель на указатель. Компилятор выдает предупреждения, потому что вы присваиваете значение p (тип int*) типу int**.

Это должно быть:

   q=&p;
   b=**q;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...