Void main void ошибка

Странные дела начинаются с short getX (Vector *v, int pos) — почему, если у вас вектор double, вы возвращаете short, а не double?

Аналогично, если у вас

double sum=0;
...
return sqrtf(sum);

и функция возвращает double, зачем же вычислять sqrtf, а не sqrt?…

void main()

неверно, нужен

int main()

Непонятно также

if (N==0) ;

И что вы хотите этим сказать? Кстати, на скриншоте у вас int main() и return после if (N==0), а вот это уже проблема: раз main возвращает int, то и return должен быть со значением, return 0;, например.

Вот все, что найдено компилятором. Правильно ли ваш код работает, а не компилируется — вопрос другой, не смотрел… Но даже навскидку:

void setN (Vector *v, int nr){
    if (nr<1) v->n=1;
    else v->n=nr;
}

Как я понимаю, это изменение размера (количества элементов) в векторе? Тогда почему вы не меняете выделенную память? А то ведь запросто может быть, что вы выделили 5 элементов, а потом сделали n сотней, и здравствуй, выход за пределы массива…

Вступление

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

Код, который вызывает UB, может работать как предполагалось в конкретной системе с конкретным компилятором, но, скорее всего, не будет работать в другой системе или с другим компилятором, версией компилятора или компилятором.

замечания

Что такое Undefined Behavior (UB)?

Неопределенное поведение — это термин, используемый в стандарте C. Стандарт C11 (ISO / IEC 9899: 2011) определяет термин неопределенное поведение как

поведение при использовании непереносимой или ошибочной программной конструкции или ошибочных данных, для которых настоящий международный стандарт не налагает никаких требований

Что произойдет, если в моем коде есть UB?

Это результаты, которые могут произойти из-за неопределенного поведения в соответствии со стандартом:

ПРИМЕЧАНИЕ. Возможное неопределенное поведение варьируется от полного игнорирования ситуации с непредсказуемыми результатами, ведения во время перевода или выполнения программы документированным образом, характерным для среды (с выдачей диагностического сообщения или без него), до прекращения перевода или выполнения (с выдача диагностического сообщения).

Следующая цитата часто используется для описания (менее формально, хотя) результатов, происходящих от неопределенного поведения:

«Когда компилятор сталкивается с [определенной неопределенной конструкцией], это законно для того, чтобы заставить демонов вылететь из вашего носа» (подразумевается, что компилятор может выбрать любой произвольно причудливый способ интерпретации кода без нарушения стандарта ANSI C)

Почему существует UB?

Если это так плохо, почему они просто не определяли его или не определяли его реализацию?

Неопределенное поведение позволяет больше возможностей для оптимизации; Компилятор может с полным основанием предположить, что любой код не содержит неопределенного поведения, что может позволить ему избежать проверок во время выполнения и выполнять оптимизации, срок действия которых был бы дорогостоящим или невозможным доказать иначе.

Почему UB трудно отслеживать?

Существует по крайней мере две причины, по которым неопределенное поведение создает ошибки, которые трудно обнаружить:

  • Компилятор не обязан — и, как правило, не может надежно — предупреждать вас о неопределенном поведении. Фактически требуя, чтобы это сделало это, явилось бы прямо против причины существования неопределенного поведения.
  • Непредсказуемые результаты могут не начинаться разворачиваться в точную точку операции, где происходит конструкция, поведение которой не определено; Неопределенное поведение окрашивает все исполнение и его последствия могут произойти в любое время: во время, после или даже до неопределенной конструкции.

Рассмотрим разворот нулевого указателя: компилятор не требуется для диагностики разыменования нулевых указателей и даже не мог, так как во время выполнения любой указатель, переданный в функцию, или в глобальной переменной может иметь значение NULL. И когда происходит разыменование нулевого указателя, стандарт не требует, чтобы программа была повреждена. Скорее, программа может произойти сбой раньше, позже или вообще не сбой; он может даже вести себя так, как если бы нулевой указатель указывал на действительный объект и вел себя нормально, только для того, чтобы сбой при других обстоятельствах.

В случае нулевого указателя разыменования, C язык отличается от управляемых языков , таких как Java или C #, где определяется поведение нуль-указатель разыменования: генерируется исключение, в точное время ( NullPointerException в Java, NullReferenceException в C #) , поэтому те, которые приходят с Java или C #, могут ошибочно полагать, что в этом случае программа C должна сбой, с выдачей диагностического сообщения или без него .

Дополнительная информация

Существует несколько таких ситуаций, которые следует четко различать:

  • Явно неопределенное поведение, то есть где стандарт C явно сообщает вам, что вы не в курсе.
  • Неявно неопределенное поведение, когда в стандарте нет текста, который предвидит поведение для ситуации, в которую вы ввели вашу программу.

Также имейте в виду, что во многих местах поведение определенных конструкций сознательно не определено стандартом C, чтобы оставить место для разработчиков компилятора и библиотек, чтобы придумать свои собственные определения. Хорошим примером являются сигналы и обработчики сигналов, где расширения C, такие как стандарт операционной системы POSIX, определяют гораздо более сложные правила. В таких случаях вам просто нужно проверить документацию своей платформы; стандарт C не может вам ничего сказать.

Также обратите внимание, что если неопределенное поведение происходит в программе, это не означает, что просто точка, где произошло неопределенное поведение, является проблематичной, а целая программа становится бессмысленной.

Из-за таких проблем важно (тем более, что компиляторы не всегда предупреждают нас о UB), чтобы программирование на языке C было, по крайней мере, знакомым с вещами, которые вызывают неопределенное поведение.

Следует отметить, что есть некоторые инструменты (например, инструменты статического анализа, такие как PC-Lint), которые помогают обнаруживать неопределенное поведение, но опять же, они не могут обнаружить все случаи неопределенного поведения.

Вызов нулевого указателя

Это пример разыменования указателя NULL, вызывающего неопределенное поведение.

int * pointer = NULL;
int value = *pointer; /* Dereferencing happens here */

Указатель NULL гарантируется стандартом C для сравнения неравного с любым указателем на действительный объект, а разыменование его вызывает неопределенное поведение.

Изменение любого объекта более одного раза между двумя точками последовательности

int i = 42;
i = i++; /* Assignment changes variable, post-increment as well */
int a = i++ + i--;

Подобный код часто приводит к размышлениям о «результирующем значении» i . Однако, вместо того, чтобы указывать результат, стандарты C указывают, что оценка такого выражения приводит к неопределенному поведению . До C2011 стандарт формализовал эти правила в терминах так называемых точек последовательности :

Между предыдущей и следующей точкой последовательности скалярный объект должен иметь значение, которое его хранимое значение изменялось не более одного раза путем оценки выражения. Кроме того, предыдущее значение должно быть считано только для определения значения, которое необходимо сохранить.

(Стандарт C99, раздел 6.5, пункт 2)

Эта схема оказалась слишком грубой, что привело к появлению некоторых выражений, демонстрирующих неопределенное поведение в отношении C99, которые, вероятно, не должны делать. C2011 сохраняет точки последовательности, но вводит более тонкий подход к этой области на основе последовательности и отношений, которые он называет «секвенированными до»:

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

(Стандарт C2011, раздел 6.5, пункт 2)

Полные детали отношения «sequenced before» слишком длинны для описания здесь, но они дополняют последовательности, а не вытесняют их, поэтому они влияют на определение поведения для некоторых оценок, поведение которых ранее не было определено. В частности, если есть точка последовательности между двумя оценками, то перед точкой последовательности «секвенируется до» после.

Следующий пример имеет четкое поведение:

int i = 42;
i = (i++, i+42); /* The comma-operator creates a sequence point */

Следующий пример имеет неопределенное поведение:

int i = 42;
printf("%d %dn", i++, i++); /* commas as separator of function arguments are not comma-operators */

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

Отсутствует оператор возврата в функции возврата значения

int foo(void) {
  /* do stuff */
  /* no return here */
}

int main(void) {
  /* Trying to use the (not) returned value causes UB */
  int value = foo();
  return 0;
}

Когда функция объявляется для возврата значения, она должна делать это на каждом возможном пути кода через нее. Неопределенное поведение возникает, как только вызывающий (который ожидает возвращаемое значение) пытается использовать возвращаемое значение 1 .

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

int foo(void) {
  /* do stuff */
  /* no return here */
}

int main(void) {
  /* The value (not) returned from foo() is unused. So, this program
   * doesn't cause *undefined behaviour*. */
  foo();
  return 0;
}

C99

main() функция является исключением из этого правила в том , что это возможно для того , чтобы быть прекращено без оператора возврата , потому что предполагается , возвращаемое значение 0 автоматически будет использоваться в данном случае 2.


1 ( ISO / IEC 9899: 201x , 6.9.1 / 12)

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

2 ( ISO / IEC 9899: 201x , 5.1.2.2.3 / 1)

достигая}, который завершает основную функцию, возвращает значение 0.

Подписанное целочисленное переполнение

В параграфе 6.5 / 5 как C99, так и C11 оценка выражения создает неопределенное поведение, если результат не является представимым значением типа выражения. Для арифметических типов это называется переполнением . Беззнаковая целочисленная арифметика не переполняется, поскольку применяется параграф 6.2.5 / 9, в результате чего любой результат без знака, который в противном случае был бы вне диапазона, был бы уменьшен до значения внутри диапазона. Однако не существует аналогичного положения для знаковых целочисленных типов; они могут и переполняются, производя неопределенное поведение. Например,

#include <limits.h>      /* to get INT_MAX */

int main(void) {
    int i = INT_MAX + 1; /* Overflow happens here */
    return 0;
}

Большинство случаев такого типа неопределенного поведения более трудно распознать или предсказать. Переполнение может в принципе возникать из-за любой операции сложения, вычитания или умножения на целые числа со знаком (с учетом обычных арифметических преобразований), где нет эффективных границ или отношений между операндами для предотвращения этого. Например, эта функция:

int square(int x) {
    return x * x;  /* overflows for some values of x */
}

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

С другой стороны, рассмотрим этот тривиальный пример переполненной цепочки со знаком целочисленной арифметики:

int zero(int x) {
    return x - x;  /* Cannot overflow */
}

Связь между операндами оператора вычитания гарантирует, что вычитание никогда не переполняется. Или рассмотрим этот несколько более практичный пример:

int sizeDelta(FILE *f1, FILE *f2) {
    int count1 = 0;
    int count2 = 0;
    while (fgetc(f1) != EOF) count1++;  /* might overflow */
    while (fgetc(f2) != EOF) count2++;  /* might overflow */

    return count1 - count2; /* provided no UB to this point, will not overflow */
}

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

Использование неинициализированной переменной

int a; 
printf("%d", a);

Переменная a — это int с автоматическим временем хранения. В приведенном выше примере пример пытается напечатать значение неинициализированной переменной ( a никогда не инициализировалось). Автоматические переменные, которые не инициализированы, имеют неопределенные значения; доступ к ним может привести к неопределенному поведению.

Примечание. Переменные со статическим или потоковым локальным хранилищем, включая глобальные переменные без static ключевого слова, инициализируются либо нулем, либо их инициализированным значением. Следовательно, законно.

static int b;
printf("%d", b);

Очень распространенная ошибка состоит в том, чтобы не инициализировать переменные, которые служат счетчиками равными 0. Вы добавляете к ним значения, но поскольку начальное значение является мусором, вы будете вызывать Undefined Behavior , например, в вопросе Компиляция на терминале выдает предупреждение указателя и странные символы .

Пример:

#include <stdio.h>

int main(void) {
    int i, counter;
    for(i = 0; i < 10; ++i)
        counter += i;
    printf("%dn", counter);
    return 0;
}

Выход:

C02QT2UBFVH6-lm:~ gsamaras$ gcc main.c -Wall -o main
main.c:6:9: warning: variable 'counter' is uninitialized when used here [-Wuninitialized]
        counter += i;
        ^~~~~~~
main.c:4:19: note: initialize the variable 'counter' to silence this warning
    int i, counter;
                  ^
                   = 0
1 warning generated.
C02QT2UBFVH6-lm:~ gsamaras$ ./main
32812

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

int main(void)
{
    int *p;
    p++; // Trying to increment an uninitialized pointer.
}

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

Вывод указателя на переменную за пределами ее срока службы

int* foo(int bar)
{
    int baz = 6;
    baz += bar;
    return &baz; /* (&baz) copied to new memory location outside of foo. */
} /* (1) The lifetime of baz and bar end here as they have automatic storage   
   * duration (local variables), thus the returned pointer is not valid! */

int main (void)
{
    int* p;

    p = foo(5);  /* (2) this expression's behavior is undefined */
    *p = *p - 6; /* (3) Undefined behaviour here */

    return 0;
}

Некоторые компиляторы с благодарностью указывают на это. Например, gcc предупреждает:

warning: function returns address of local variable [-Wreturn-local-addr]

и clang предупреждает:

warning: address of stack memory associated with local variable 'baz' returned 
[-Wreturn-stack-address]

для вышеуказанного кода. Но компиляторы, возможно, не смогут помочь в сложном коде.

(1) Возвращаемая ссылка на переменную объявленную static определяется поведением, поскольку переменная не уничтожается после выхода из текущей области.

(2) Согласно ISO / IEC 9899: 2011 6.2.4 §2 «Значение указателя становится неопределенным, когда объект, на который он указывает, достигает конца своего срока службы».

(3) Разыменование указателя, возвращаемого функцией foo является неопределенным поведением, поскольку память, на которую он ссылается, содержит неопределенное значение.

Деление на ноль

int x = 0;
int y = 5 / x;  /* integer division */

или же

double x = 0.0;
double y = 5.0 / x;  /* floating point division */

или же

int x = 0;
int y = 5 % x;  /* modulo operation */

Для второй строки в каждом примере, где значение второго операнда (x) равно нулю, поведение не определено.

Обратите внимание, что большинство реализаций математики с плавающей запятой будут следовать стандарту (например, IEEE 754), и в этом случае операции, такие как деление на ноль, будут иметь согласованные результаты (например, INFINITY ), даже если в стандарте C указано, что операция не определена.

Доступ к памяти за пределами выделенного фрагмента

A указатель на кусок памяти, содержащий n элементов, может быть разыменован только в том случае, если он находится в memory диапазона и memory + (n - 1) . Выделение указателя за пределами этого диапазона приводит к неопределенному поведению. В качестве примера рассмотрим следующий код:

int array[3];
int *beyond_array = array + 3;
*beyond_array = 0; /* Accesses memory that has not been allocated. */

Третья строка обращается к четвертому элементу в массиве, длина которого составляет всего 3 элемента, что приводит к неопределенному поведению. Точно так же поведение второй строки в следующем фрагменте кода также недостаточно четко определено:

int array[3];
array[3] = 0;

Обратите внимание, что указание последнего элемента массива не является неопределенным поведением ( beyond_array = array + 3 здесь четко определено), но разыменование его ( *beyond_array — неопределенное поведение). Это правило также выполняется для динамически распределенной памяти (например, буферов, созданных через malloc ).

Копирование перекрывающейся памяти

Среди их эффектов множество разнообразных стандартных библиотечных функций — копирование последовательностей байтов из одной области памяти в другую. Большинство из этих функций имеют неопределенное поведение, когда области источника и получателя перекрываются.

Например, это …

#include <string.h> /* for memcpy() */

char str[19] = "This is an example";
memcpy(str + 7, str, 10);

… пытается скопировать 10 байт, где области памяти источника и назначения перекрываются тремя байтами. Чтобы визуализировать:

               overlapping area
               |
               _ _
              |   |
              v   v
T h i s   i s   a n   e x a m p l e 
^             ^
|             |
|             destination
|
source

Из-за перекрытия результирующее поведение не определено.

Среди стандартных библиотечных функций с ограничением такого рода являются memcpy() , strcpy() , strcat() , sprintf() и sscanf() . В стандарте говорится об этих и некоторых других функциях:

Если копирование происходит между перекрывающимися объектами, поведение не определено.

Функция memmove() является основным исключением из этого правила. Его определение указывает, что функция ведет себя так, как если исходные данные были сначала скопированы во временный буфер, а затем записаны на целевой адрес. Не существует исключения для перекрытия областей источника и получателя, а также никакой необходимости в одном, поэтому memmove() имеет memmove() поведение в таких случаях.

Различие отражает эффективность против . общий компромисс. Копирование таких функций, как эти функции, обычно происходит между непересекающимися областями памяти, и часто во время разработки можно узнать, будет ли конкретный экземпляр копирования памяти в эту категорию. Предполагая, что не-перекрытие дает сравнительно более эффективные реализации, которые не дают достоверных результатов, когда предположение не выполняется. Большинство функций библиотеки C допускают более эффективные реализации, а memmove() заполняет пробелы, обслуживая случаи, когда источник и получатель могут или перекрываются. Однако для обеспечения правильного эффекта во всех случаях он должен выполнять дополнительные тесты и / или использовать сравнительно менее эффективную реализацию.

Чтение неинициализированного объекта, который не поддерживается памятью

C11

Чтение объекта приведет к неопределенному поведению, если объект равен 1 :

  • неинициализированным
  • с автоматической продолжительностью хранения
  • его адрес никогда не принимается

Переменная a в приведенном ниже примере удовлетворяет всем этим условиям:

void Function( void )
{
    int a;
    int b = a;
} 

1 (Цитируется по: ISO: IEC 9899: 201X 6.3.2.1 Lvalues, массивы и обозначения функций 2)
Если lvalue обозначает объект с продолжительностью автоматического хранения, который мог быть объявлен с классом хранения регистров (никогда не был принят его адрес), и этот объект не инициализирован (не объявлен с инициализатором, и его назначение не было выполнено до использования ), поведение не определено.

Гонка данных

C11

C11 представила поддержку для нескольких потоков исполнения, что дает возможность расследовать данные. Программа содержит гонку данных, если к объекту в ней обращаются 1 двумя разными потоками, где по крайней мере один из доступа является неатомным, по крайней мере один изменяет объект, а семантика программы не позволяет гарантировать, что два доступа не могут перекрываться во время. 2 Хорошо помните, что фактическая параллельность задействованных доступов не является условием гонки данных; Гонки данных охватывают более широкий класс проблем, возникающих из (разрешенных) несоответствий в представлениях разных потоков.

Рассмотрим этот пример:

#include <threads.h>

int a = 0;

int Function( void* ignore )
{
    a = 1;

    return 0;
}

int main( void )
{
    thrd_t id;
    thrd_create( &id , Function , NULL );

    int b = a;

    thrd_join( id , NULL );
}

Основные вызовы нити thrd_create , чтобы начать новую нить работает функция Function . Второй поток изменяет a , а основной поток читает a . Ни один из этих доступов не является атомарным, и эти два потока ничего не делают ни индивидуально, ни совместно, чтобы гарантировать, что они не перекрываются, поэтому существует гонка данных.

Среди способов, с помощью которых эта программа могла избежать гонки данных,

  • основной поток может выполнять свое чтение из перед началом другого потока; a
  • основной поток может выполнять свое чтение из после обеспечения с помощью a thrd_join , что другие прекратившие;
  • потоки могли синхронизировать их обращения через мьютекс, каждый из которых блокировал этот мьютекс, прежде чем получить доступ к a и разблокировать его позже.

Как показывает опция mutex, избегая гонки данных, не требуется обеспечить определенный порядок операций, например, дочерний поток, модифицирующий a до того, как основной поток прочитает его; достаточно (для избежания гонки данных) обеспечить, чтобы для данного исполнения один доступ выполнялся перед другим.


1 Изменение или чтение объекта.

2 (Цитируется по ISO: IEC 9889: 201x, раздел 5.1.2.4 «Многопоточные исполнения и расписания данных»)
Выполнение программы содержит гонку данных, если она содержит два конфликтующих действия в разных потоках, по крайней мере один из которых не является атомарным, и не происходит до другого. Любая такая гонка данных приводит к неопределенному поведению.

Чтение значения указателя, который был освобожден

Даже просто считывание значения освобожденного указателя (т. Е. Без попытки разыменования указателя) является неопределенным поведением (UB), например

char *p = malloc(5);
free(p);
if (p == NULL) /* NOTE: even without dereferencing, this may have UB */
{

}

Цитирование ISO / IEC 9899: 2011 , раздел 6.2.4. §2:

[…] Значение указателя становится неопределенным, когда объект, на который он указывает (или только что прошел), достигает конца своего срока службы.

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

Изменить строковый литерал

В этом примере кода указатель char p инициализируется адресом строкового литерала. Попытка изменить строковый литерал имеет неопределенное поведение.

char *p = "hello world";
p[0] = 'H'; // Undefined behavior

Однако изменение измененного массива char напрямую или через указатель, естественно, не является неопределенным поведением, даже если его инициализатор является литеральной строкой. Хорошо:

char a[] = "hello, world";
char *p = a;

a[0] = 'H';
p[7] = 'W';

Это связано с тем, что строковый литерал эффективно копируется в массив каждый раз, когда массив инициализируется (один раз для переменных со статической продолжительностью, каждый раз, когда массив создается для переменных с автоматической или длительностью потока — переменные с назначенной продолжительностью не инициализируются) и это прекрасно, чтобы изменить содержимое массива.

Освобождение памяти дважды

Освободить память дважды — это неопределенное поведение, например

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

Цитата из стандарта (7.20.3.2. Свободная функция C99):

В противном случае, если аргумент не соответствует указателю, ранее возвращенному функцией calloc, malloc или realloc, или если пространство было освобождено вызовом free или realloc, поведение не определено.

Использование неверного спецификатора формата в printf

Использование неверного спецификатора формата в первом аргументе printf вызывает неопределенное поведение. Например, приведенный ниже код вызывает неопределенное поведение:

long z = 'B';
printf("%cn", z);

Вот еще один пример

printf("%fn",0);

Над строкой кода указано неопределенное поведение. %f ожидает двойной. Однако 0 имеет тип int .

Обратите внимание, что ваш компилятор обычно может помочь вам избежать таких случаев, если вы включите соответствующие флаги во время компиляции ( -Wformat в clang и gcc ). Из последнего примера:

warning: format specifies type 'double' but the argument has type
      'int' [-Wformat]
    printf("%fn",0);
            ~~    ^
            %d

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

Следующие могут иметь неопределенное поведение из-за неправильного выравнивания указателя:

 char *memory_block = calloc(sizeof(uint32_t) + 1, 1);
 uint32_t *intptr = (uint32_t*)(memory_block + 1);  /* possible undefined behavior */
 uint32_t mvalue = *intptr;

Неопределенное поведение происходит по мере преобразования указателя. Согласно C11, если преобразование между двумя типами указателей приводит к некорректному результату (6.3.2.3), поведение не определено . Здесь uint32_t может потребовать выравнивания 2 или 4, например.

calloc с другой стороны, требуется вернуть указатель, подходящий для любого типа объекта; поэтому memory_block правильно выровнен, чтобы содержать uint32_t в своей начальной части. Затем в системе, где uint32_t требует выравнивания 2 или 4, memory_block + 1 будет нечетным адресом и, следовательно, не будет правильно выровнен.

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

Кастинг char * для указателей на другие типы без каких-либо проблем с выравниванием иногда используется неправильно для декодирования упакованных структур, таких как заголовки файлов или сетевые пакеты.

Вы можете избежать неопределенного поведения, связанного с неправильным преобразованием указателя, используя memcpy :

memcpy(&mvalue, memory_block + 1, sizeof mvalue);

Здесь не происходит преобразования указателя в uint32_t* и байты копируются один за другим.

Эта операция копирования для нашего примера приводит только к допустимому значению mvalue потому что:

  • Мы использовали calloc , поэтому байты правильно инициализированы. В нашем случае все байты имеют значение 0 , но любая другая правильная инициализация.
  • uint32_t — это точный тип ширины и не имеет битов заполнения
  • Любой произвольный битовый шаблон является допустимым представлением для любого неподписанного типа.

Сложение или вычитание указателя неправильно ограничено

Следующий код имеет неопределенное поведение:

char buffer[6] = "hello";
char *ptr1 = buffer - 1;  /* undefined behavior */
char *ptr2 = buffer + 5;  /* OK, pointing to the '' inside the array */
char *ptr3 = buffer + 6;  /* OK, pointing to just beyond */
char *ptr4 = buffer + 7;  /* undefined behavior */

В соответствии с C11, если сложение или вычитание указателя на объект или объект, находящийся за ним за пределы объекта, приводит к результату, который не указывает на один объект массива или только за ним, поведение не определено (6.5.6 ).

Кроме того, это естественно неопределенное поведение для разыменования указателя, который указывает только на массив:

char buffer[6] = "hello";
char *ptr3 = buffer + 6;  /* OK, pointing to just beyond */
char value = *ptr3;       /* undefined behavior */

Изменение константной переменной с помощью указателя

int main (void)
{
    const int foo_readonly = 10;
    int *foo_ptr;

    foo_ptr = (int *)&foo_readonly; /* (1) This casts away the const qualifier */
    *foo_ptr = 20; /* This is undefined behavior */

    return 0;
}

Цитирование ISO / IEC 9899: 201x , раздел 6.7.3 §2:

Если предпринимается попытка изменить объект, определенный с помощью типа, соответствующего const, с использованием значения lvalue с неконстантированным классом, поведение не определено. […]


(1) В GCC это может вызвать следующее предупреждение: warning: assignment discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]

Передача нулевого указателя на преобразование printf% s

Преобразование %s printf утверждает, что соответствующий аргумент является указателем на исходный элемент массива типа символа . Нулевой указатель не указывает на начальный элемент любого массива символьного типа, и поэтому поведение следующего не определено:

char *foo = NULL;
printf("%s", foo); /* undefined behavior */

Однако неопределенное поведение не всегда означает, что программа вылетает из строя — некоторые системы предпринимают шаги, чтобы избежать сбоя, который обычно происходит, когда нулевой указатель разыменовывается. Например, Glibc, как известно, печатает

(null)

для кода выше. Однако добавьте (просто) новую строку в строку формата, и вы получите сбой:

char *foo = 0;
printf("%sn", foo); /* undefined behavior */

В этом случае это происходит потому, что GCC имеет оптимизацию, которая возвращает printf("%sn", argument); в вызов puts с puts(argument) , и puts в Glibc не обрабатывает нулевые указатели. Все это поведение стандартно.

Обратите внимание: нулевой указатель отличается от пустой строки . Итак, справедливо следующее и не имеет неопределенного поведения. Он просто напечатает новую строку :

char *foo = "";
printf("%sn", foo);

Несогласованная привязка идентификаторов

extern int var;
static int var; /* Undefined behaviour */

C11, §6.2.2, 7 гласит:

Если внутри единицы перевода один и тот же идентификатор появляется как с внутренней, так и с внешней связью, поведение не определено.

Обратите внимание: если предыдущее объявление идентификатора будет видимым, оно будет иметь связь с предыдущим объявлением. C11, §6.2.2, 4 позволяет:

Для идентификатора, объявленного с указанием класса хранилища extern в области, в которой видна предварительная декларация этого идентификатора, 31), если предыдущее объявление указывает внутреннюю или внешнюю связь, связь идентификатора с последующим объявлением такая же, как и связь, указанная в предыдущей декларации. Если никакое предварительное объявление не видно или если в предыдущем объявлении не указано никакой привязки, идентификатор имеет внешнюю связь.

/* 1. This is NOT undefined */
static int var;
extern int var; 


/* 2. This is NOT undefined */
static int var;
static int var; 

/* 3. This is NOT undefined */
extern int var;
extern int var; 

Использование fflush на входном потоке

Стандарты POSIX и C явно fflush что использование fflush во входном потоке является неопределенным поведением. fflush определяется только для выходных потоков.

#include <stdio.h>

int main()
{
    int i;
    char input[4096];

    scanf("%i", &i);
    fflush(stdin); // <-- undefined behavior
    gets(input);

    return 0;
}

Нет стандартного способа удаления непрочитанных символов из входного потока. С другой стороны, некоторые реализации используют fflush для очистки буфера stdin . Microsoft определяет поведение fflush во входном потоке: если поток открыт для ввода, fflush очищает содержимое буфера. Согласно POSIX.1-2008, поведение fflush не определено, если входной файл не доступен для поиска.

Дополнительную информацию см. В разделе Использование fflush(stdin) .

Бит-сдвиг с использованием отрицательных отсчетов или за пределами ширины типа

Если значение счетчика сдвига является отрицательным значением, то обе операции сдвига влево и вправо не определены 1 :

int x = 5 << -3; /* undefined */
int x = 5 >> -3; /* undefined */

Если сдвиг влево выполняется по отрицательному значению , он не определен:

int x = -5 << 3; /* undefined */

Если сдвиг влево выполняется по положительному значению, и результат математического значения не представляется в типе, он не определен 1 :

/* Assuming an int is 32-bits wide, the value '5 * 2^72' doesn't fit 
 * in an int. So, this is undefined. */
       
int x = 5 << 72;

Обратите внимание, что сдвиг вправо по отрицательному значению (.eg -5 >> 3 ) не является неопределенным, а определяется реализацией .


1 Цитирование ISO / IEC 9899: 201x , раздел 6.5.7:

Если значение правого операнда отрицательное или больше или равно ширине продвинутого левого операнда, поведение не определено.

Изменение строки, возвращаемой функциями getenv, strerror и setlocale

Изменение строк, возвращаемых стандартными функциями getenv() , strerror() и setlocale() не определено. Таким образом, реализации могут использовать статическое хранилище для этих строк.

Функция getenv (), C11, §7.22.4.7, 4 , говорит:

Функция getenv возвращает указатель на строку, связанную с элементом согласованного списка. Указанная строка не должна изменяться программой, но может быть перезаписана последующим вызовом функции getenv.

Функция strerror (), C11, §7.23.6.3, 4 говорит:

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

Функция setlocale (), C11, §7.11.1.1, 8 гласит:

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

Точно так же функция localeconv() возвращает указатель на struct lconv который не должен быть изменен.

Функция localeconv (), C11, §7.11.2.1, 8 гласит:

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

Возврат из функции, объявленной с помощью спецификатора функции `_Noreturn` или` noreturn`

C11

Спецификатор функции _Noreturn был введен в C11. Заголовок <stdnoreturn.h> предоставляет макрос noreturn который расширяется до _Noreturn . Поэтому использование _Noreturn или noreturn из <stdnoreturn.h> является прекрасным и эквивалентным.

Функция, объявленная с помощью _Noreturn (или noreturn ), не может вернуться к вызывающей noreturn . Если такая функция не вернется к абоненту, поведение не определено.

В следующем примере func() объявляется с noreturn спецификатора noreturn но возвращается к вызывающему.

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

noreturn void func(void);

void func(void)
{
    printf("In func()...n");
} /* Undefined behavior as func() returns */

int main(void)
{
    func();
    return 0;
}

gcc и clang вызывают предупреждения для вышеуказанной программы:

$ gcc test.c
test.c: In function ‘func’:
test.c:9:1: warning: ‘noreturn’ function does return
 }
 ^
$ clang test.c
test.c:9:1: warning: function declared 'noreturn' should not return [-Winvalid-noreturn]
}
^

Пример использования noreturn который имеет четко определенное поведение:

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

noreturn void my_exit(void);

/* calls exit() and doesn't return to its caller. */
void my_exit(void)
{
    printf("Exiting...n");
    exit(0);
}

int main(void)
{
    my_exit();
    return 0;
}

gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

1

05.02.2012, 12:49. Показов 9878. Ответов 29

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Вот код программы, между void и main выдает ошибку declaration syntax error, что я не так делаю? моя первая прога на с++, поэтому прошу помощи)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z
 
   void main()
{
   clrscr();
   printf("Vvedite a:");
   scanf("%d";&a);
   printf("Vvedite b:");
   scanf("%d";&b);
   printf("Vvedite x:");
   scanf("%d";&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(ln(y)*6)))/(6-cos(y));
   printf("z=%d",z);
   getch();
}



0



Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 12:54

2

gylayko, по стандарту функция main должа возвращать значение типа int.



0



Полярный

476 / 448 / 158

Регистрация: 11.09.2011

Сообщений: 1,156

05.02.2012, 12:56

3

Цитата
Сообщение от gylayko
Посмотреть сообщение

float x,y,a,b,z

semicolon ; забыли

silent_1991,

Цитата
Сообщение от gylayko
Посмотреть сообщение

#include<math.h>
\…

getch();

Видимо в борланде работает -> на void ему пофиг.
А так лучше конечно на int поправить



0



silent_1991

05.02.2012, 12:57

Не по теме:

Цитата
Сообщение от dimcoder
Посмотреть сообщение

semicolon ; забыли

А вот на это даже не смотрел))



0



BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:01

5

И на это вот:

C
1
2
3
4
5
scanf("%d";&a);
   printf("Vvedite b:");
   scanf("%d";&b);
   printf("Vvedite x:");
   scanf("%d";&x);



0



Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:03

6

dimcoder, расширение не выдаёт борланд, ибо это Pure C (правда, насколько он Pure в борланде, я не знаю). А вот clrscr(); выдаёт.



0



30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:04

 [ТС]

7

Цитата
Сообщение от silent_1991
Посмотреть сообщение

gylayko, по стандарту функция main должа возвращать значение типа int.

а у меня возвращает типа float, а что тогда нужно вместо void main() ? при замене переенных на тип int ошибка не пропадает)



0



silent_1991

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:06

8

Цитата
Сообщение от gylayko
Посмотреть сообщение

а у меня возвращает типа float

ЩИТО?

Цитата
Сообщение от gylayko
Посмотреть сообщение

при замене переенных на тип int

А переменный тут при чём? По стандарту функция main может быть описана либо как

C
1
int main(void);

, либо как

C
1
int main(int argc, char *argv[]);



0



BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:09

9

Так должно работать:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z;
 
   int main()
{
   printf("Vvedite a:");
   scanf("%d",&a);
   printf("Vvedite b:");
   scanf("%d",&b);
   printf("Vvedite x:");
   scanf("%d",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%d",z);
   getch();
   return 0;
}



0



gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:12

 [ТС]

10

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

Так должно работать:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z;
 
   int main()
{
   printf("Vvedite a:");
   scanf("%d",&a);
   printf("Vvedite b:");
   scanf("%d",&b);
   printf("Vvedite x:");
   scanf("%d",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%d",z);
   getch();
   return 0;
}

все равно перед main та же ошибка!



0



silent_1991

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:15

11

А вот так будет даже правильно работать. И будет выглядеть более-менее верно с точки зрения стиля.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<math.h>
#include<stdio.h>
#include<conio.h>
 
int main(void)
{
    float x, y, a, b, z;
    
    printf("Vvedite a:");
    scanf("%f", &a);
    printf("Vvedite b:");
    scanf("%f", &b);
    printf("Vvedite x:");
    scanf("%f", &x);
    
    y = 0.02;
    z = ((sin(2 * x - b * b) - 7 * a * (y * y)) / (x * x * x * x + 1)) - (sqrt(cos(y) - 5 * (exp(log(y) * 6))) / (6 - cos(y)));
    
    printf("z=%f", z);
    
    getch();
    
    return 0;
}



0



Полярный

476 / 448 / 158

Регистрация: 11.09.2011

Сообщений: 1,156

05.02.2012, 13:16

12

Цитата
Сообщение от gylayko
Посмотреть сообщение

все равно перед main та же ошибка!

Среду разработки и компилер назовите. Скомпилел на борланд 3.1 все работает.



0



BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:17

13

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #include<math.h>
  #include<stdio.h>
float x,y,a,b,z;
   int main()
{
   printf("Vvedite a:");
   scanf("%f",&a);
   printf("Vvedite b:");
   scanf("%f",&b);
   printf("Vvedite x:");
   scanf("%f",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%f",z);
   return 0;
}

http://liveworkspace.org/code/… c9afa745ce
Как бы не думал, что он ошибку выдаст. Максимум предупреждение



1



gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:25

 [ТС]

14

Цитата
Сообщение от dimcoder
Посмотреть сообщение

Среду разработки и компилер назовите. Скомпилел на борланд 3.1 все работает.

тот же борланд 3.1 только через dosbox ибо 64 бит!

Добавлено через 57 секунд

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #include<math.h>
  #include<stdio.h>
float x,y,a,b,z;
   int main()
{
   printf("Vvedite a:");
   scanf("%f",&a);
   printf("Vvedite b:");
   scanf("%f",&b);
   printf("Vvedite x:");
   scanf("%f",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%f",z);
   return 0;
}

http://liveworkspace.org/code/… c9afa745ce
Как бы не думал, что он ошибку выдаст. Максимум предупреждение

а что за программа на фото? так ведь удобнее! без всяких досбоксов и т.д. работает?



0



4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:26

15

Цитата
Сообщение от gylayko
Посмотреть сообщение

а что это за программа на фото?

Если Вы о ссылке, то это онлайн компилер. Кстати, вещь удобная)



0



30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:29

 [ТС]

16

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

Если Вы о ссылке, то это онлайн компилер. Кстати, вещь удобная)

ну да, там все работает также как и у Вас! а через обычный компилятор борланд 3.1 нифига!



0



Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:32

17

Цитата
Сообщение от gylayko
Посмотреть сообщение

обычный компилятор борланд 3.1

А потому что это не обычный компилятор. Это чрезвычайно древний компилятор, ему уже 20 лет. за это время успели выпустить три стандарта и несколько правок к ним.



0



4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:34

18

Цитата
Сообщение от gylayko
Посмотреть сообщение

ну да, там все работает также как и у Вас! а через обычный компилятор борланд 3.1 нифига!

Это говорит о том, что код правильный. Но в онлайн компиляторе можно только проверять на ошибки. Поэтому стоит найти лучше что-нибудь поновей борланда, типа dev-cpp. Лучше конечно сразу MVC.



0



Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:36

19

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

MVC

Не очень хороший совет, у него есть некоторые проблемы со стандартом.

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

dev-cpp

Не такая уж она и новая.

gylayko, советую среду, к которой можно подключить любой компилятор (на ваш выбор) и компилятор mingw, как можно новее (последняя релизная версия 4.6.2).



0



4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:40

20

Цитата
Сообщение от silent_1991
Посмотреть сообщение

Не очень хороший совет, у него есть некоторые проблемы со стандартом.

По крайней мере уж с такими ошибками должен справляться

Слышал, что WxDev-cpp вроде как обновляется.



0



qubaidolla

0 / 0 / 0

Регистрация: 04.01.2020

Сообщений: 1

1

04.01.2020, 08:08. Показов 6429. Ответов 2

Метки c++ (Все метки)


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;
void main /* Проблема в нем () */
{
    setlocale (LC_ALL, "rus");
 
    int a;
    cin >> a;
 
    switch (a)
 
    {
    case 1:
        cout << "Вы ввели 1";
        break;
    
    case 2:
        cout << "Вы ввели 2";
        break;
    
    default:
        cout << "Я не понимаю";
        break;  
    }
 
 
cin.get();
return 0;
}

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

0

5666 / 3112 / 1299

Регистрация: 07.02.2019

Сообщений: 7,806

04.01.2020, 08:09

2

int main()

1

653 / 466 / 183

Регистрация: 23.04.2019

Сообщений: 1,987

04.01.2020, 17:14

3

0

IT_Exp

Эксперт

87844 / 49110 / 22898

Регистрация: 17.06.2006

Сообщений: 92,604

04.01.2020, 17:14

3

I have typed in the following code in Ubuntu using Emacs and compiled using the command line

#include <stdio.h>

int main(void)
{
  printf("Hello World!nn");
  return 0;
}

Having the void in the main function argument returns the following warning

helloworld.c: In function ‘main’:
helloworld.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

When I removed the «void» within the parenthesis the program compiled without any errors. What is incorrect in have main(void) in this program?

Compilation command is
gcc -Wall -ggdb helloworld.c -o hello

Edit:
This is the screenshot which I would like to share
enter image description here

asked Dec 23, 2015 at 19:48

Prasanna's user avatar

PrasannaPrasanna

3032 silver badges16 bronze badges

6

The error doesn’t have anything to do with the void in the signature of main() int main(void) is correct and is the way to define main() when you don’t need to handle command line arguments.

The error means that you defined int main(void) and you did not return a value from the function. Like this

#include <stdio.h>

int main(void) 
{
    printf("Hello World!n");    
}

This warning was removed for main() in newer versions of gcc because main() implicitly returns 0 when the program exits unless you indicate otherwise with exit() or an explict return from main().

Normal functions still trigger this warning and it helps in prevention of undefined behavior due to not returning from a function and trying to capture the return value.

answered Dec 23, 2015 at 19:51

Iharob Al Asimi's user avatar

Iharob Al AsimiIharob Al Asimi

52.4k6 gold badges59 silver badges96 bronze badges

2

The only way that warning could be for main() function is if you don’t have a return statement and you are compiling in C89/C90 mode.

Since C99, a return statement at the end of main() is not required and it’ll be assumed to return 0; if control returns from main()‘s end. So compile in c99 or C11 mode:

gcc -Wall -ggdb -std=c11 helloworld.c -o hello

which won’t trigger that warning. Or make sure you have return statement if you are compiling in c89/C90. Until recently (at least upto gcc 4.9), the default mode in gcc is gnu90. So you would get that warning withot a return statement if you don’t passstd=.

I presume you don’t actually have return 0; in your real code that produces this warning as it wouldn’t matter in what mode of C you are compiling it if you had an explicit return statement.

answered Dec 23, 2015 at 20:06

P.P's user avatar

P.PP.P

116k20 gold badges170 silver badges231 bronze badges

9

I have typed in the following code in Ubuntu using Emacs and compiled using the command line

#include <stdio.h>

int main(void)
{
  printf("Hello World!nn");
  return 0;
}

Having the void in the main function argument returns the following warning

helloworld.c: In function ‘main’:
helloworld.c:6:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

When I removed the «void» within the parenthesis the program compiled without any errors. What is incorrect in have main(void) in this program?

Compilation command is
gcc -Wall -ggdb helloworld.c -o hello

Edit:
This is the screenshot which I would like to share
enter image description here

asked Dec 23, 2015 at 19:48

Prasanna's user avatar

PrasannaPrasanna

3032 silver badges16 bronze badges

6

The error doesn’t have anything to do with the void in the signature of main() int main(void) is correct and is the way to define main() when you don’t need to handle command line arguments.

The error means that you defined int main(void) and you did not return a value from the function. Like this

#include <stdio.h>

int main(void) 
{
    printf("Hello World!n");    
}

This warning was removed for main() in newer versions of gcc because main() implicitly returns 0 when the program exits unless you indicate otherwise with exit() or an explict return from main().

Normal functions still trigger this warning and it helps in prevention of undefined behavior due to not returning from a function and trying to capture the return value.

answered Dec 23, 2015 at 19:51

Iharob Al Asimi's user avatar

Iharob Al AsimiIharob Al Asimi

52.4k6 gold badges59 silver badges96 bronze badges

2

The only way that warning could be for main() function is if you don’t have a return statement and you are compiling in C89/C90 mode.

Since C99, a return statement at the end of main() is not required and it’ll be assumed to return 0; if control returns from main()‘s end. So compile in c99 or C11 mode:

gcc -Wall -ggdb -std=c11 helloworld.c -o hello

which won’t trigger that warning. Or make sure you have return statement if you are compiling in c89/C90. Until recently (at least upto gcc 4.9), the default mode in gcc is gnu90. So you would get that warning withot a return statement if you don’t passstd=.

I presume you don’t actually have return 0; in your real code that produces this warning as it wouldn’t matter in what mode of C you are compiling it if you had an explicit return statement.

answered Dec 23, 2015 at 20:06

P.P's user avatar

P.PP.P

116k20 gold badges170 silver badges231 bronze badges

9

This my main function:

void main(int argc, char **argv)
{
    if (argc >= 4)
    {
        ProcessScheduler *processScheduler;
        std::cout <<
            "Running algorithm: " << argv[2] <<
            "nWith a CSP of: " << argv[3] <<
            "nFilename: " << argv[1] <<
            std::endl << std::endl;

        if (argc == 4)
        {
            processScheduler = new ProcessScheduler(
                argv[2],
                atoi(argv[3])
            );
        }
        else
        {
            processScheduler = new ProcessScheduler(
                argv[2],
                atoi(argv[3]),
                atoi(argv[4]),
                atoi(argv[5])
            );
        }
        processScheduler -> LoadFile(argv[1]);
        processScheduler -> RunProcesses();

        GanntChart ganntChart(*processScheduler);
        ganntChart.DisplayChart();
        ganntChart.DisplayTable();
        ganntChart.DisplaySummary();

        system("pause");

        delete processScheduler;
    }
    else
    {
        PrintUsage();
    }
}

The error I get when I compile is this:

Application.cpp:41:32: error: ‘::main’ must return ‘int’

It’s a void function how can I return int and how do I fix it?

Michael's user avatar

Michael

3,0547 gold badges36 silver badges78 bronze badges

asked Nov 2, 2016 at 14:05

SPLASH's user avatar

3

Try doing this:

int main(int argc, char **argv)
{
    // Code goes here

    return 0;
}

The return 0; returns a 0 to the operating system which means that the program executed successfully.

answered Nov 2, 2016 at 14:07

Michael's user avatar

MichaelMichael

3,0547 gold badges36 silver badges78 bronze badges

5

C++ requires main() to be of type int.

roottraveller's user avatar

answered Nov 2, 2016 at 14:18

Nick Pavini's user avatar

Nick PaviniNick Pavini

2923 silver badges14 bronze badges

3

Function is declared as int main(..);, so change your void return value to int, and return 0 at the end of the main function.

answered Nov 2, 2016 at 14:14

renonsz's user avatar

renonszrenonsz

5611 gold badge4 silver badges17 bronze badges

  • Forum
  • Beginners
  • void main problem

void main problem

i am trying to use this given tutorial and main needs to be void for future tutorials, but every time i compile it as void, it gives an error saying main must return an int. Although on the tutorial it worked.
I know math.h and string do not need to be there, but it is for future purposes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <math.h>
#include <string>
using namespace std;


void main()
{
    int people;
    float bill, tip, totaltip, total;

    cout << "How much is the bill? ";
    cin >> bill;
    cout <<"How many people will be splitting the bill? ";
    cin >> people;
    cout << "What is the percetage of the tip? ";
    cin >> tip;

    totaltip = bill *(tip/100.);
    total = (totaltip + bill) /people;

    cout << "The total tip at %" << tip << " is $" << totaltip << '.' << endl;
    cout << "Each person will pay $" << total << '.' << endl;
   
}

Last edited on

metulburr wrote:
main must return an int

Last edited on

though it works on other peoples tutorials?

I would probably find a different tutorial…

The standard says main must return an int, but apparently some compilers will let you get away with void. I just tested with msvc 2010, and it will compile

without warning.

yeah dude, main() most definitely returns an int. Consider this simple boilerplate code:
int main(int nArgs, char* pszArgs)

its kinda just what i was told to impliment in all my main methods and i would be safe

Topic archived. No new replies allowed.

Функция main() возвращает тип int. Если вы уже это знаете, то и не читайте.

Если вы присвоите функции main() тип возврата, отличный от int, то в компиляторах, предшествующих компиляторам С99, вы получите неопределенное поведение своей программы. В компиляторах С99 вы получите неспецифицированное поведение, если так говорит реализация версии, или неопределенное поведение — если она этого не делает. Доверяете ли вы своей программе в этом отношении?

Многие просто не верят мне, когда я говорю им это (точно так же, как не верил я, когда впервые узнал об этом). Частично это связано с тем, что несколько широко известных учебников по С и, по крайней мере, по одной авторитетной программе-компилятору используют void main() с тревожной регулярностью. Ниже приведена формулировка стандарта С99 (который фактически чуть более снисходителен, чем стандарт С89, который вам, возможно, более знаком):

5.1.2.2.1. Запуск программы. Функция, вызывающая запуск программы, называется main (главная). Реализация не объявляет прототип для этой функции. Он должен быть определен путем возврата целого типа int без параметров:

int main (void) {  /*  …  */  }

либо с двумя параметрами (здесь они называются argc и argv, хотя можно использовать любые имена в том порядке, как они размещены в функции, в которой объявлены):

int main (int argc, char *argv[] ) {  /*  …   */  }

либо некоторым другим определенным реализацией способом».

5.1.2.2.3. Завершение программы. Если возвращаемый главной функцией тип является типом, совместимым с int, то возврат в главную функцию эквивалентен вызову функции выхода со значением, возвращенным главной функцией в качестве ее аргумента; при достижении скобки }, которая завершает главную функцию, возвращается значение 0. Если возвращаемый тип несовместим с типом int, состояние завершения, возвращаемое в хост-среду, является неспецифицированным».

В данном контексте «неспецифицированный» означает, что стандарт не требует какого-либо специфического поведения от компилятора, который волен возвратить в хост-среду (обычно это операционная система) любое состояние, какое ему нравится, и это применяется, только если документами реализации установлено, что она поддерживает возвращаемые из main () типы, отличные от int. Если у вас пустая (void) главная функция main () и вы пишете код для ядерного реактора или военного самолета, вы, возможно, почувствуете легкую нерешительность, и я не виню вас. Кроме того, определение main () для возврата типа void (пустой) не является синтаксической ошибкой или нарушением ограничения, так что компилятор не обязательно должен выдавать какое-либо диагностическое сообщение.

Давайте посмотрим на это несколько под иным углом. Рассмотрим четвертый аргумент функции сортировки qsort. Он специфицирован как указатель на некую функцию сравнения, принимающую в качестве аргументов две константы типа const void * и возвращающую тип int. Функция qsort вызывает эту функцию сравнения и использует возвращенное ею значение для установления взаимоотношений между двумя объектами в массиве, который подлежит сортировке. Так вот, что случится, если вы напишете функцию сравнения, подобную этой?

void CompInts (const void *pl,  const void *p2)
{
    const int  *nl  = pi;
    const int  *n2  = p2;
    int diff;
    if(*nl > *n2)
        diff = 1;
    else if(*nl == *n2)
        diff = 0;
    else
        diff = -1;
}

Слов нет, верно? У функции qsort нет способа получить информацию, в которой она нуждается. Вы не можете специфицировать прототип функций сравнения — вам потребуется отбросить правила обращения к функции qsort, если вы хотите заставить эту функцию делать то, чего от нее ожидаете.

Хорошо, вернемся к функции main (). Здесь точно такая же ситуация. Вы не ответственны за определение интерфейса main(). Для этого есть вызывающая функция. Кто вызывает main()? Это не вы (хотя фактически вы можете, если захотите, вызвать main(), точно так же как вы можете при желании вызвать свою функцию сравнения из qsort). Но первичным «заказчиком» функции main() является код запуска. Как же код запуска определит, успешно ли завершилась программа, если вы не сообщите ему об этом? Этот вызов «сидит» где-то глубоко во внутренностях системы (здесь я немного упростил его):

int returnstatus;
returnstatus = main  (argc,  argv);

Если вы «опустошите» функцию main (), появится несколько интересных возможностей:

  • Программа может работать в точности так, как вы ожидаете.
  • returnstatus может попасть в ловушку и вызвать аварийный отказ программы (либо всего компьютера).
  • Код запуска может отправить поддельный код возврата операционной системе, которая затем решит перемотать назад транзакции базы данных, поскольку программа не возвратила ожидаемого значения.
  • А это хуже всего — код запуска может снаружи достигнуть вашего носа и начать извлекать из него демонов. (Демон (Demon) — процедура, запускаемая автоматически при выполнении некоторых условий и характеризуемая непредсказуемостью поведения. — Прим. науч. ред.).

Функция main () возвращает тип int. Существует только три переносимых на другие платформы значения, которые вы можете вернуть из main ():

  • 0
  • EXITSDCCESS
  • EXIT_FAILURE

Два последние определены в <stdlib.h>, и их фактические значения варьируются в зависимости от конкретной системы. (Другими словами, не следует отыскивать эти значения в библиотеке <stdlib.h> и переносить их в свою программу.)

Если вы вернули 0, код запуска сообщит операционной системе или другой хост-среде, что ваша программа выполнилась успешно, переведя 0 при необходимости в некоторое другое значение.

Количество аргументов функции main ()

Фактически функцию можно определить путем определения реализации. Следовательно, такое определение main, как

ИЛИ

int main  (int argc,  char **argv,  char **env)

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

Ниже приведены переносимые определения функции main ():

  • int main (void)
  • int main (int argc, char **argv)
  • int main (int argc, char **argv [ ] )
  • Любое определение, в точности эквивалентное любому из трех предыдущих

Таким образом, вы можете использовать различные имена переменных в качестве argc и argv, а также можете использовать FOO, если определению предшествует typedef int FOO, и т.д. Но чтобы возвращаемое значение было переносимым, из main вы должны возвращать тип int, а также задавать либо ни одного аргумента, либо два специфицированных стандартом аргумента. Если есть необходимость получить доступ к среде переносимым способом, можете, конечно, использовать функцию getenv ().

© Ричард Хэзфилд, «Искусство программирования на C», 2001 год.

Looks like no one’s replied in a while. To start the conversation again, simply

ask a new question.

Hey there. I’ve just started taking a object-oriented C++ course online — it’s been a few years since I’ve programmed C++, although I’ve programmed C more recently. Anyways, they expect me to use Visual Studio as my compiler, but I’m not budging — Xcode is where I like to write my code, and I don’t feel like reinstalling Parallels. The problem is, the code I’m supposed to use for one of the exercises defines main() using ‘void’ instead of ‘int’. In my experience programming C (and C++ if I’m not mistaking), this has never been a problem. However, with Xcode I’m getting an error that says, «error: ‘::main’ must return ‘int’». Can anyone toss me some insight into why I’m getting this error, and how I may be able to correct it so that the compiler accepts main() as ‘void’? I’ve checked the project settings under «GCC 4.0 — Language», but I didn’t find anything I could recognize as relevant, other than «C Language Dialect» being set to C99, and I don’t think that’s the issue.

Any help is appreciated — thanks.

MacBook,

Mac OS X (10.5.8)

Posted on Sep 5, 2010 4:21 AM

Tron55555 wrote:

So I guess there’s no easy way around that then?

The easy answer is to use int. Like a number of things in the Windows world, «void main()» is flat-out syntactically invalid. The Microsoft Foundation Class library will not compile with a standards-compliant C++ compiler — because it isn’t valid C++. Microsoft’s compilers have switches to enable standards compliance, but you should never use them. GCC has switches to enable it to compile MFC, but no one ever uses them.

Apple gets a lot of press with the iPad and iPhone, but the reality is that Macs are still a distant minority in any corporate/educational environment. University professors, including those in Computer Science, are known for living 20 years in the past.

You are going to have to do what every Mac user in a computer science class has always done, write your code on your Mac because you love the Mac, then port it to Windows or whatever else. You are going to need Parallels for this course. The end result is that your code will be better than anyone else’s in the class. You have to write code good enough to satisfy two compilers and you will be a better programmer for it.

Posted on Sep 6, 2010 6:24 AM

error with ‘void main()’ in C++ tool

Перейти к контенту

Странные дела начинаются с short getX (Vector *v, int pos) — почему, если у вас вектор double, вы возвращаете short, а не double?

Аналогично, если у вас

double sum=0;
...
return sqrtf(sum);

и функция возвращает double, зачем же вычислять sqrtf, а не sqrt?…

void main()

неверно, нужен

int main()

Непонятно также

if (N==0) ;

И что вы хотите этим сказать? Кстати, на скриншоте у вас int main() и return после if (N==0), а вот это уже проблема: раз main возвращает int, то и return должен быть со значением, return 0;, например.

Вот все, что найдено компилятором. Правильно ли ваш код работает, а не компилируется — вопрос другой, не смотрел… Но даже навскидку:

void setN (Vector *v, int nr){
    if (nr<1) v->n=1;
    else v->n=nr;
}

Как я понимаю, это изменение размера (количества элементов) в векторе? Тогда почему вы не меняете выделенную память? А то ведь запросто может быть, что вы выделили 5 элементов, а потом сделали n сотней, и здравствуй, выход за пределы массива…

gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

1

05.02.2012, 12:49. Показов 9867. Ответов 29

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Вот код программы, между void и main выдает ошибку declaration syntax error, что я не так делаю? моя первая прога на с++, поэтому прошу помощи)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z
 
   void main()
{
   clrscr();
   printf("Vvedite a:");
   scanf("%d";&a);
   printf("Vvedite b:");
   scanf("%d";&b);
   printf("Vvedite x:");
   scanf("%d";&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(ln(y)*6)))/(6-cos(y));
   printf("z=%d",z);
   getch();
}

0

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 12:54

2

gylayko, по стандарту функция main должа возвращать значение типа int.

0

Полярный

476 / 448 / 158

Регистрация: 11.09.2011

Сообщений: 1,156

05.02.2012, 12:56

3

Цитата
Сообщение от gylayko
Посмотреть сообщение

float x,y,a,b,z

semicolon ; забыли

silent_1991,

Цитата
Сообщение от gylayko
Посмотреть сообщение

#include<math.h>

getch();

Видимо в борланде работает -> на void ему пофиг.
А так лучше конечно на int поправить

0

silent_1991

05.02.2012, 12:57

Не по теме:

Цитата
Сообщение от dimcoder
Посмотреть сообщение

semicolon ; забыли

А вот на это даже не смотрел))

0

BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:01

5

И на это вот:

C
1
2
3
4
5
scanf("%d";&a);
   printf("Vvedite b:");
   scanf("%d";&b);
   printf("Vvedite x:");
   scanf("%d";&x);

0

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:03

6

dimcoder, расширение не выдаёт борланд, ибо это Pure C (правда, насколько он Pure в борланде, я не знаю). А вот clrscr(); выдаёт.

0

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:04

 [ТС]

7

Цитата
Сообщение от silent_1991
Посмотреть сообщение

gylayko, по стандарту функция main должа возвращать значение типа int.

а у меня возвращает типа float, а что тогда нужно вместо void main() ? при замене переенных на тип int ошибка не пропадает)

0

silent_1991

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:06

8

Цитата
Сообщение от gylayko
Посмотреть сообщение

а у меня возвращает типа float

ЩИТО?

Цитата
Сообщение от gylayko
Посмотреть сообщение

при замене переенных на тип int

А переменный тут при чём? По стандарту функция main может быть описана либо как

C
1
int main(void);

, либо как

C
1
int main(int argc, char *argv[]);

0

BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:09

9

Так должно работать:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z;
 
   int main()
{
   printf("Vvedite a:");
   scanf("%d",&a);
   printf("Vvedite b:");
   scanf("%d",&b);
   printf("Vvedite x:");
   scanf("%d",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%d",z);
   getch();
   return 0;
}

0

gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:12

 [ТС]

10

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

Так должно работать:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include<math.h>
  #include<stdio.h>
  #include<conio.h>
float x,y,a,b,z;
 
   int main()
{
   printf("Vvedite a:");
   scanf("%d",&a);
   printf("Vvedite b:");
   scanf("%d",&b);
   printf("Vvedite x:");
   scanf("%d",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%d",z);
   getch();
   return 0;
}

все равно перед main та же ошибка!

0

silent_1991

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:15

11

А вот так будет даже правильно работать. И будет выглядеть более-менее верно с точки зрения стиля.

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<math.h>
#include<stdio.h>
#include<conio.h>
 
int main(void)
{
    float x, y, a, b, z;
    
    printf("Vvedite a:");
    scanf("%f", &a);
    printf("Vvedite b:");
    scanf("%f", &b);
    printf("Vvedite x:");
    scanf("%f", &x);
    
    y = 0.02;
    z = ((sin(2 * x - b * b) - 7 * a * (y * y)) / (x * x * x * x + 1)) - (sqrt(cos(y) - 5 * (exp(log(y) * 6))) / (6 - cos(y)));
    
    printf("z=%f", z);
    
    getch();
    
    return 0;
}

0

Полярный

476 / 448 / 158

Регистрация: 11.09.2011

Сообщений: 1,156

05.02.2012, 13:16

12

Цитата
Сообщение от gylayko
Посмотреть сообщение

все равно перед main та же ошибка!

Среду разработки и компилер назовите. Скомпилел на борланд 3.1 все работает.

0

BumerangSP

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:17

13

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #include<math.h>
  #include<stdio.h>
float x,y,a,b,z;
   int main()
{
   printf("Vvedite a:");
   scanf("%f",&a);
   printf("Vvedite b:");
   scanf("%f",&b);
   printf("Vvedite x:");
   scanf("%f",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%f",z);
   return 0;
}

http://liveworkspace.org/code/… c9afa745ce
Как бы не думал, что он ошибку выдаст. Максимум предупреждение

1

gylayko

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:25

 [ТС]

14

Цитата
Сообщение от dimcoder
Посмотреть сообщение

Среду разработки и компилер назовите. Скомпилел на борланд 3.1 все работает.

тот же борланд 3.1 только через dosbox ибо 64 бит!

Добавлено через 57 секунд

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #include<math.h>
  #include<stdio.h>
float x,y,a,b,z;
   int main()
{
   printf("Vvedite a:");
   scanf("%f",&a);
   printf("Vvedite b:");
   scanf("%f",&b);
   printf("Vvedite x:");
   scanf("%f",&x);
   y=0.02;
   z=((sin(2*x-b*b)-7*a*(y*y))/(x*x*x*x+1))-(sqrt(cos(y)-5*(exp(log(y)*6)))/(6-cos(y)));
   printf("z=%f",z);
   return 0;
}

http://liveworkspace.org/code/… c9afa745ce
Как бы не думал, что он ошибку выдаст. Максимум предупреждение

а что за программа на фото? так ведь удобнее! без всяких досбоксов и т.д. работает?

0

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:26

15

Цитата
Сообщение от gylayko
Посмотреть сообщение

а что это за программа на фото?

Если Вы о ссылке, то это онлайн компилер. Кстати, вещь удобная)

0

30 / 29 / 15

Регистрация: 28.09.2011

Сообщений: 449

05.02.2012, 13:29

 [ТС]

16

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

Если Вы о ссылке, то это онлайн компилер. Кстати, вещь удобная)

ну да, там все работает также как и у Вас! а через обычный компилятор борланд 3.1 нифига!

0

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:32

17

Цитата
Сообщение от gylayko
Посмотреть сообщение

обычный компилятор борланд 3.1

А потому что это не обычный компилятор. Это чрезвычайно древний компилятор, ему уже 20 лет. за это время успели выпустить три стандарта и несколько правок к ним.

0

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:34

18

Цитата
Сообщение от gylayko
Посмотреть сообщение

ну да, там все работает также как и у Вас! а через обычный компилятор борланд 3.1 нифига!

Это говорит о том, что код правильный. Но в онлайн компиляторе можно только проверять на ошибки. Поэтому стоит найти лучше что-нибудь поновей борланда, типа dev-cpp. Лучше конечно сразу MVC.

0

Эксперт С++

5054 / 3115 / 271

Регистрация: 11.11.2009

Сообщений: 7,045

05.02.2012, 13:36

19

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

MVC

Не очень хороший совет, у него есть некоторые проблемы со стандартом.

Цитата
Сообщение от BumerangSP
Посмотреть сообщение

dev-cpp

Не такая уж она и новая.

gylayko, советую среду, к которой можно подключить любой компилятор (на ваш выбор) и компилятор mingw, как можно новее (последняя релизная версия 4.6.2).

0

4299 / 1421 / 463

Регистрация: 16.12.2010

Сообщений: 2,939

Записей в блоге: 3

05.02.2012, 13:40

20

Цитата
Сообщение от silent_1991
Посмотреть сообщение

Не очень хороший совет, у него есть некоторые проблемы со стандартом.

По крайней мере уж с такими ошибками должен справляться

Слышал, что WxDev-cpp вроде как обновляется.

0

  • Forum
  • Beginners
  • void main problem

void main problem

i am trying to use this given tutorial and main needs to be void for future tutorials, but every time i compile it as void, it gives an error saying main must return an int. Although on the tutorial it worked.
I know math.h and string do not need to be there, but it is for future purposes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <math.h>
#include <string>
using namespace std;


void main()
{
    int people;
    float bill, tip, totaltip, total;

    cout << "How much is the bill? ";
    cin >> bill;
    cout <<"How many people will be splitting the bill? ";
    cin >> people;
    cout << "What is the percetage of the tip? ";
    cin >> tip;

    totaltip = bill *(tip/100.);
    total = (totaltip + bill) /people;

    cout << "The total tip at %" << tip << " is $" << totaltip << '.' << endl;
    cout << "Each person will pay $" << total << '.' << endl;
   
}

Last edited on

metulburr wrote:
main must return an int

Last edited on

though it works on other peoples tutorials?

I would probably find a different tutorial…

The standard says main must return an int, but apparently some compilers will let you get away with void. I just tested with msvc 2010, and it will compile

without warning.

yeah dude, main() most definitely returns an int. Consider this simple boilerplate code:
int main(int nArgs, char* pszArgs)

its kinda just what i was told to impliment in all my main methods and i would be safe

Topic archived. No new replies allowed.

Looks like no one’s replied in a while. To start the conversation again, simply

ask a new question.

Hey there. I’ve just started taking a object-oriented C++ course online — it’s been a few years since I’ve programmed C++, although I’ve programmed C more recently. Anyways, they expect me to use Visual Studio as my compiler, but I’m not budging — Xcode is where I like to write my code, and I don’t feel like reinstalling Parallels. The problem is, the code I’m supposed to use for one of the exercises defines main() using ‘void’ instead of ‘int’. In my experience programming C (and C++ if I’m not mistaking), this has never been a problem. However, with Xcode I’m getting an error that says, «error: ‘::main’ must return ‘int’». Can anyone toss me some insight into why I’m getting this error, and how I may be able to correct it so that the compiler accepts main() as ‘void’? I’ve checked the project settings under «GCC 4.0 — Language», but I didn’t find anything I could recognize as relevant, other than «C Language Dialect» being set to C99, and I don’t think that’s the issue.

Any help is appreciated — thanks.

MacBook,

Mac OS X (10.5.8)

Posted on Sep 5, 2010 4:21 AM

Tron55555 wrote:

So I guess there’s no easy way around that then?

The easy answer is to use int. Like a number of things in the Windows world, «void main()» is flat-out syntactically invalid. The Microsoft Foundation Class library will not compile with a standards-compliant C++ compiler — because it isn’t valid C++. Microsoft’s compilers have switches to enable standards compliance, but you should never use them. GCC has switches to enable it to compile MFC, but no one ever uses them.

Apple gets a lot of press with the iPad and iPhone, but the reality is that Macs are still a distant minority in any corporate/educational environment. University professors, including those in Computer Science, are known for living 20 years in the past.

You are going to have to do what every Mac user in a computer science class has always done, write your code on your Mac because you love the Mac, then port it to Windows or whatever else. You are going to need Parallels for this course. The end result is that your code will be better than anyone else’s in the class. You have to write code good enough to satisfy two compilers and you will be a better programmer for it.

Posted on Sep 6, 2010 6:24 AM

error with ‘void main()’ in C++ tool

error: ‘::main’ must return ‘int’

#include <iostream>

using namespace std;

int i=1;
void main()
{
    int i=i;
}

There was an error running:

error: '::main' must return 'int'

Reason: The C language standard allows the main function to be of type void. According to the C++ standard, main must be of type int.

Intelligent Recommendation

Main() error report-crazy delivery (not) return

Main’s error report-crazy delivery (not) return main() error Change the number of parameters Change parameter type But after all About the call stack Linux View Adjustment Windows View Adjustment (Com…

int main() void main()

Write a directory title here C/C++ :void main() C C++ void main int main( int argc, char *argv[], char *envp[] ) ? C/C++ :void main() void main(), , C , , void main(), int main() ? ? ? , C Primer Plus…

More Recommendation

error C4716 must return a value. Processing

problem The following error was reported, but I couldn’t find how to solve it. Record it here. error C4716: «TApamaInterface::GetEventValue»: Must return a value error C4716: «TApamaInt…

  • Void callback const mqtt publish pub ошибка
  • Voicemod произошла неожиданная ошибка
  • Voicemod ошибка настройки аудиоустройства
  • Voice install could not be verified ошибка
  • Vngame exe ошибка приложения rising storm 2 vietnam