Я начинающий программист и изучаю свой первый язык C.
Я учусь в основном по книге Deitel and Deitel C How to Programming, но также использую примеры задач и вещи из университета, однако я застрял на одном.
У меня очень базовое понимание указателей - добавление & перед переменной заставляет ее печатать адрес, а * использует указатель для использования значения, хранящегося по этому адресу или тому подобному.
Кусок кода, который я написал, предназначен для вычисления наибольшего (наибольшего?) Общего знаменателя двух чисел, и на самом деле он вообще не требует и не включает указатели. Он использует две функции, и вся логика правильная, потому что он выводит правильный ответ на экран, если я делаю это из второй функции, а не возвращаю его в основную. Вот в чем проблема.
Когда вторая функция возвращает значение ответа, по какой-то причине она возвращает то, что я могу предположить только как указатель. Понятия не имею, почему он это делает. Я мог бы поработать с этим и преобразовать его для поиска значения - однако, похоже, это указатель, локальный для второй функции, и он записан поверх. Ничего из того, что я мог найти в Интернете или в своей книге, не подсказало мне, как решить эту проблему.
Спасибо, если вы дочитали до этого места. Я слишком много бродил.
Вот мой код и результат. Любая помощь или указатели (извините за каламбур) были бы очень признательны. Я знаю, что могу просто напечатать его во второй функции, но я бы предпочел знать, как и почему он не возвращает значение, которое мне хотелось бы.
Код
#include <stdio.h>
int greatestCD (int num1, int num2);
int main(void)
{
int a=0, b=0;
int result;
printf("Please enter two numbers to calculate the greatest common denominator from\n");
scanf("%d%d", &a, &b);
result = greatestCD (a,b);
printf("Using the correct in main way:\nThe greatest common denominator of %d and %d is %d\n",a,b, result);
}
int greatestCD (int num1 ,int num2)
{
if (num2==0){
printf("Using the cheaty in gcd function way:\nThe greatest common denominator is %d\n",num1);
return num1;
} else {
greatestCD(num2,(num1%num2));
}
}
Вывод (используя 12 и 15 - ответ должен быть 3)
C:\Users\Sam\Documents\C programs>gcd
Please enter two numbers to calculate the greatest common denominator from
12
15
Using the cheaty in gcd function way:
The greatest common denominator is 3
Using the correct in main way:
The greatest common denominator of 12 and 15 is 2293524
Такое простое решение от frankodwyer. Это такие крошечные вещи, которые я либо не могу заметить, либо не знаю. Итак, то, что возвращалось, не было указателем, а было просто мусором?
Бесконечно благодарен.





Вы ничего не возвращаете из своей функции, поэтому значение 2293524 - это просто случайный мусор. Разве ваш компилятор не предупреждает вас об отсутствии возвращаемого значения?
Вам не хватает оператора return в последней строке функции maximumCD ()
greatestCD(num2,(num1%num2));
Сделай это
return greatestCD(num2,(num1%num2));
(вам, возможно, еще предстоит отладка, но именно поэтому он возвращает мусор ... вы не говорите ему, что еще вернуть)
edit: Я также предлагаю, чтобы при компиляции в будущем вы включали все предупреждения компилятора ... если вы используете gcc, попробуйте добавить флаг -Стена в свою команду компиляции. Это должно предупредить вас, когда вы делаете что-то, что может привести к подобным ошибкам. (Не каждое такое предупреждение обязательно является ошибкой, отсюда «предупреждение», но обычно оно указывает на возможную проблему.)
Скорее всего, это был указатель, но это просто то, что уже было в местоположении возвращаемого значения. Например, на x86 вы получили то значение, которое компилятор поместил в регистр eax.
Более странно то, что программа работает на моей Linux-машине. Ошибка или особенность gcc?
/dev/shm $ gcc x.c
/dev/shm $ ./a.out
Please enter two numbers to calculate the greatest common denominator from
12
15
Using the cheaty in gcd function way:
The greatest common denominator is 3
Using the correct in main way:
The greatest common denominator of 12 and 15 is 3
/dev/shm $ gcc --version
gcc (Debian 4.3.2-1) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
скорее всего, возвращаемое значение просто случайно оказалось в нужном регистре в то время.
Я изменил код, чтобы проверить версию функции gcd, в которой отсутствует ключевое слово return, с исправленной версией, и для всех i, j <5000 функция работает правильно.
Он также работал правильно (с отсутствующим возвратом или без него) на OSX с использованием gcc.
Неопределенное поведение позволяет программе случайно работать правильно. Не полагайтесь на него - поведение не определено, и GCC не требуется для поддержания согласованности между выпусками, и он может сломаться, когда захочет. Любой другой компилятор может делать все, что ему нравится: искать «гнусные демоны» в Google.
Поскольку вы изучаете C, независимо от ошибки, связанной с отсутствием возврата, вот несколько наблюдений и советов:
Указатели - это самая сложная особенность языка для изучения, особенно когда вы попадаете в malloc() и free(). Не расстраивайтесь.
Выбросьте Deitel и Deitel и получите себе копию Керниган и Ричи. Это одна из лучших когда-либо написанных языковых книг.
Включите все предупреждения постоянно. Если вы можете использовать MacOS или Linux, gcc -Wall -Werror -O вполне подойдет.
Запустите каждую программу C под Valgrind. Valgrind - замечательный инструмент, разработанный для ловить ошибки в том, как вы используете указатели. Это спасет ваш бекон!
Удачи!
Есть ли конкретная причина, по которой вы говорите, чтобы выбросить Deitel и Deitel, или это просто потому, что язык программирования C - это ТАКАЯ книга?
Deitel и Deitel известны как фабрика по производству учебников. Я предпочитаю получать информацию от людей, которые приложили руку к разработке языка или, по крайней мере, проделали большую его разработку. Я также считаю, что книги короче - лучше. Никогда не видел любой Deitel & Deitel мне нравилось ...
См. Вопрос Не следует ли мне использовать книгу Херба Шильдта, чтобы учиться? и, в частности, список, указанный в http://www.cs.technion.ac.il/users/yechiel/CS/BadBooksC+C++.html. Хотя в нем указана книга Deitel и Deitel о C++, существует тенденция сильного семейного сходства между книгами данной пары авторов. Я был бы склонен купить себе хорошую книгу по C. Я научился у Керниган и Ритчи (первое издание, когда было только одно издание), поэтому я бы порекомендовал ее - она краткая и точная (как и сама C).
Спасибо за полезные ссылки. У меня будет копия Kernighan & Ritchie по дороге из Amazon в новом году.
Огромное спасибо. То есть то, что возвращалось, было просто мусором, а не указателем?