Печать указанного значения из переданного указателя - PullRequest
0 голосов
/ 01 июля 2019

Я не понимаю, почему этот код успешно возвращает мне правильный ввод.

#include <stdio.h>
#include <stdlib.h>

int bintest();

int main()
{
        int* x = malloc(sizeof(int));
        printf("\n\n*****\nEnter value of x\n*****\n");
        scanf("\n%d", &x);
        bintest(x); 
}

int bintest(int* y)
{
        printf("\ny: %d", y);
}

Почему это не работает, когда я печатаю ** y, я предполагаю, что указатель x передается в bintest и сохраняется вуказатель y, который затем должен называться ** y для вывода значения ввода?

Ответы [ 5 ]

3 голосов
/ 01 июля 2019

Это неопределенное поведение.

Это работает по следующей причине:

&x - адрес указателя x.Поскольку размер указателя обычно равен по крайней мере int, scanf("\n%d", &x); просто перезаписывает указатель.Затем вы передаете этот указатель (значение которого теперь соответствует тому, что набрал пользователь) в bintest

Ваш компилятор должен был выдать вам как минимум два предупреждения, таких как:

'scanf': строка формата'% d 'требует аргумент типа' int * ', но аргумент 1 переменной имеет тип' int ** '
' printf ': строка формата'% d 'требует аргумент типа' int ', но аргумент variadic 1 имеет тип 'int *'

Эти два предупреждения являются скорее ошибками, и вы не должны их игнорировать.

3 голосов
/ 01 июля 2019

Вы должны начать включать предупреждения компилятора и обращать на них внимание.Ваш короткий фрагмент дает 3!Предупреждения.

$ gcc main.c -Wall -Wextra
main.c: In function ‘main’:
main.c:12:19: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int **’ [-Wformat=]
         scanf("\n%d", &x);
                  ~^   ~~
main.c: In function ‘bintest’:
main.c:18:23: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
         printf("\ny: %d", y);
                      ~^   ~
                      %ls
main.c:19:5: warning: control reaches end of non-void function [-Wreturn-type]
     }
     ^

Ваша программа имеет неопределенное поведение, и это может проявиться, работая должным образом.

Правильный код должен быть

scanf("\n%d", x);
...
printf("\ny: %d", *y);

И объявитьbintest как функция void, если вы не хотите ничего возвращать.

Я не понимаю, почему этот код успешно возвращает мне правильный ввод.

Вы сохраняете значение чтения в указателе x, который создает утечку памяти, поскольку вы отбрасываете вызов malloc.Вы можете удалить вызов malloc, и ваша программа будет вести себя так же.(Вероятно. Это имеет неопределенное поведение).

1 голос
/ 01 июля 2019

Вы НЕ сохранили значение целого числа в x IF, что вы хотели;Вы попросили пользователя ввести данные и переписали указатель x на значение, предоставленное пользователем.Этот указатель x теперь указывает на то, что дал пользователь.

Позже вы передадите этот х в эту функцию и напечатаете это значение: так вы получите то, что предоставил пользователь.

Однако ваш НЕ МОЖЕТ ссылаться на него.Х указывает на предоставленное пользователем значение.Какое значение это?Знаете ли вы, что это какое-то действительное место в памяти.

Лучше всего прочитать справочную документацию по scanf.

Если вы действительно хотите сохранить целое число x с предоставленным пользователем значением, код выглядит как

int x;scanf (... & x).

Затем вы передаете & x этой функции.

0 голосов
/ 01 июля 2019

Если вы хотите отсканировать значение, на которое указывает x, используйте x , например: scanf("\n%d", x).Чтобы напечатать значение, которое вы только что поместили, передайте x следующим образом: bintest(x);, но напечатайте * y следующим образом: printf("%d", *y);

scanf("\n%d", &x); - это то же самое, что x = scan;

scanf("\n%d", x); - это то же самое, что и *x = scan;, что вам нужно.

Так что в этом примере scanf("\n%d", &x); вы даете scanf & x, который является адресом самого x.Это означает, что scanf изменит значение x, изменяя то, на что указывает x.Функция scanf хочет адрес туда, где она помещает свое значение.Таким образом, чтобы поместить его туда, куда указывает х, вам нужно просто ввести x .

Причина, по которой ваши значения совпадают, заключается в том, что вы просто передаете x вот так: bintest(x); и печать y вот так: printf("%d", y);.В этом примере y является просто копией x.

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

    #include <stdio.h>
    #include <stdlib.h>

    int bintest();

    int main(){

        int* x = malloc(sizeof(int));

        printf("value of x:       %d\n",x);
        printf("address of x:     %d\n",&x);
        printf("value at %d: %d\n", x, *x);;

        printf("\n\n*****\nEnter value of x\n*****\n");
        scanf("\n%d", x);

        printf("value of x:       %d\n",x);
        printf("address of x:     %d\n",&x);
        printf("value at %d: %d\n", x, *x);
        bintest(x);
    }

    int bintest(int* y){
        printf("\ny: %d", *y);
    }

Вы должны получить вывод, подобный следующему:

value of x:       7018424
address of x:     6422316
value at 7018424: 7017768

*****
Enter value of x
*****
99
value of x:       7018424
address of x:     6422316
value at 7018424: 99

y: 99
0 голосов
/ 01 июля 2019

Поддерживая сказанное @Jabberwocky,

test.c: In function ‘main’:
test.c:7:12: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int **’ [-Wformat=]
    7 |  scanf("\n%d", &x);
      |           ~^   ~~
      |            |   |
      |            |   int **
      |            int *
test.c: In function ‘bintest’:
test.c:11:16: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
   11 |  printf("\ny: %d", y);
      |               ~^   ~
      |                |   |
      |                int int *
      |               %ls
test.c:12:1: warning: control reaches end of non-void function [-Wreturn-type]
   12 | }
      | ^

Это произошло, когда я попытался скомпилировать код с помощью CLion IDE (gcc (GCC) 9.1.1 20190503 (Red Hat 9.1.1-1), C11), хотя даже я не до конца его понимаю. Я надеюсь, что это поможет, и кто-то может объяснить это дальше.

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