[c] Следует ли приводить типы?

feliks28

Есть ситуация:
ExitProcess(GetLastError;

Это функции из WinApi, где ExitProcess принимает параметр UINT (unsigned int а GetLastError возвращает параметр DWORD (unsigned long)
Т.к. у меня на компьютере int равен long, то все прекрасно компилируется. А что произойдет на компьютерах, где int не равен long'у?
И как оформить код с прицелом на такой случай? Как выше? Или
ExitProcessUINT)GetLastError;
Или
ExitProcess(/*(UINT)*/GetLastError;
?
Кстати, добавил в начало #define STRICT, думал ругаться начнет, но тишина. А в каких случаях тогда будет ругаться?
Компилятор gcc 3.4.5 (mingw special)

tokuchu

Вроде как int-ы автоматически приводятся туда-сюда.

Vladislav177Rus

Где-то видел табличку названий архитектур в зависимости от соотношения длины в них стандартных Си-типов. Не уверен 100%, но кажется, во всех Windows sizeof(long) = sizeof(int)

aleks058

Если код компилируется на какой-либо платформе, он будет компилиться везде. Ибо стандарт.
В любом случае, для компилятора unsigned int != unsigned long, следовательно так как все компилится, он производит приведение типов самостоятельно.

Reves2

При преобразование unsigned int в unsigned long по стандарту возможна потеря точности, так как в стандарте не написанна, что у них одинаковый размер. Написанно, что он меньше или равен. На всех совремменных win платформах, начиная с 95, он одинаковый .

Realist

Потеря точности у может быть у вещественных чисел. Целые числа и так точны. Тут, вероятно, стоит говорить о возможном переполнении.
Какая потеря / переполнение может быть при переходе от меньшего типа к большему?

Realist

Если код компилируется на какой-либо платформе, он будет компилиться везде. Ибо стандарт.

Совершенно НЕверно. Еще более ошибочно утверждение о том, что если программа работает на одной платформе, то она будет работать везде.

feliks28

На всех совремменных win платформах, начиная с 95, он одинаковый
Даже на 64-битных?

Realist

int нормально расширится до long.
Ничего тут делать не надо.

feliks28

Ага, спасибо. Значит для винды оставлю 1й вариант.
А в целях общего образования: если у нас аналогичная ситуация и не винда, то какой из этих вариантов? Или вообще не так?

Realist

Ну по логике вещей расширение делается автоматически, а на сужение компилятор выдаст предупреждение (если его попросить выдавать предупреждения).
Явное преобразование подавит предупреждение, но тут надо понимать, что больший тип в меньший в любом случае не влезет. Если реально используется значение, которое не умещается в меньший тип, ты его потеряешь.
Далее, ты действительно пишешь на С, а не на C++? В последнем случае следует использовать другие операторы приведения типов.

feliks28

Хм. Сначала, честно говоря, не поверил, что для того чтобы компилятор ругался на присвоение short'у long'а нужно ему что-то сказать. Проверил: оказывается нужно. Только вот фиг знает что: gcc.info проглядел, но все -W... похожие по описанию точно так же молчат.
Кто-нибудь из работавших c gcc нужную опцию не подскажет?
p.s. Да, на чистом си.

erotic

А при чем тут, собсно, винда? Я бы понял, если бы это определялось архитектурой, конкретным железом или в конце концов по разному разными компилаторами. Но почему именно винда?

slonishka

-pedantic ?

feliks28


-pedantic ?
А у тебя оно работает? У меня тишина:
test.c:
int main(void) {
long testl = 65636;
short tests = testl;

return 0;
}
gcc -pedantic test.c

slonishka

хз, вроде должно. мне лень проверять, честно говоря.
мб -Wall -pedantic ?
я щас в ман заглянул, на как-то там много. ну его нах. =)

feliks28

Мне не лень, я проверил. У меня тишина. Так что вовсе и не "вроде должно"

slonishka

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

Werdna

Не уверен 100%, но кажется, во всех Windows sizeof(long) = sizeof(int)
У тебя уже неизлечимая стадия виндузятника. "Во всех виндовс" — это, конечно, перл. А ты задумывался, что это не от современности современной ОС виндовс зависит, а от платформы? Впрочем, виндузятники не думают, они себе поставят 5 виндовсов и будут "тестировать".
По поводу вопроса аффтора треда — твоя функция ExitProcess — это что? Обертка над exit? если да, то возвращается при выходе программы int, но чаще всего делают так: при ошибке возвращают -1. Если тебе надо уточнить какой именно был результат выхода — пиши в соотв. лог ПОЛНУЮ ДИАГНОСТИКУ, а не дурацкий номер ошибки. И вот почему:
Сама идея кода возврата из приложения — это вернуть "успех" или "провал". Сделано это в основном для такого типа вещей: "prog_a && prog_b && prog_c", чтобы оборвать цепочку: если какая-то из программ не отработала. После обычного запуска твой код возврата теряется, если не был вытащен специально, например, когда ты процесс запускаешь из другого и смотришь код возврата. Опять же, и в том случае лучше о провале сообщить кратко "-1", и как-то по-другому передать полную диагностику.
Почему не стоит передавать именно сам код ошибки? Всё просто — толку от него будет не много. "Can't open file" — сразу встает вопрос какой. "Пермишн денаед" — где и кому, и за что? Во всех таких случаях нужна _ПОДРОБНАЯ_ диагностика: что за ошибка, при попытке чего, что именно не так. В некоторых случаях стоит также написать типичные причины и методы их устранения.
При таком подходе твоя программа будет вызывать любовь к себе и к её аффтару.

agaaaa

У тебя уже неизлечимая стадия виндузятника. "Во всех виндовс" — это, конечно, перл. А ты задумывался, что это не от современности современной ОС виндовс зависит, а от платформы? Впрочем, виндузятники не думают, они себе поставят 5 виндовсов и будут "тестировать".
В основном это зависит от компилятора. Платформа просто накладывает какие-то рамки.
По поводу вопроса аффтора треда — твоя функция ExitProcess — это что? Обертка над exit?

В Windows ExitProcess - функция WinAPI. Стандратная функция exit реализована через неё.
Вообще говоря, ничто не мешает выводить отадочную информацию, а потом всё-таки возвращать с помощью exit код ошибки.

banderon

Тоже попробовал, и тоже gcc не ругается.
Но вот на такой код он все же ругнулся
dsme /tmp $ cat test.c
int main (void) {
int test = 0x100000000ul;
(void) test;

return 0;
}
dsme /tmp $ make
gcc -O0 -W -Wall -ansi -pedantic test.c -o test
test.c: В функции ‘main’
test.c:2: предупреждение: переполнение при неявном преобразовании константы

Reves2

Проблема в том что автор треда не правильно написал. ExitProcess - на вход получает UINT, а GetLastError возвращает DWORD. Так что проблема теоритически существует.

feliks28

Да, my bad Хотя, по приведению к (UINT) ниже в посте понятно, что ошибся...
А ведь два раза вчера перечитал прежде чем отправить
Исправил.

feliks28

Ну, небеглое прочтение показывает, что -Wall врубает далеко не все warning'и.
Вот зафигачил все что нашел для C в gcc.info в один батник (чтобы не разъезжалось разбил строку обратными слешами):
gcc test.c -O2 -Wdisabled-optimization -pedantic -Werror -Wall -Wextra -Wfloat-equal -Wdeclaration-after-statement -Wundef -Wendif-labels \
-Wshadow -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Waggregate-return -Wstrict-prototypes \
-Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wmissing-noreturn -Wmissing-format-attribute -Wpacked \
-Wpadded -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Winvalid-pch -Wlong-long

Не включил опции -Wtraditional, -Wsystem-headers и -Wlarger-than-LEN
И один фиг gcc молчит зараза такая!

Vladislav177Rus

Вообще говоря, Windows не является кроссплатформенной ОС, и существует очень ограниченный набор систем, на которых она запускается. Происходит это, в частности, ввиду того, что во всех системных библиотеках и заголовочных файлах используются определенные соглашения, такие как sizeof(long) == sizeof(int). Таким образом, твое замечание не только необдуманное и глупое, но и свидетельствует о банальном незнании матчасти.
Оставить комментарий
Имя или ник:
Комментарий: