#include <stdio.h>
int main() {
unsigned long long int num = 285212672; //FYI: fits in 29 bits
int normalInt = 5;
printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
return 0;
}
Wynik:
My number is 8 bytes wide and its value is 285212672l. A normal number is 0.
Zakładam, że ten nieoczekiwany wynik pochodzi z drukowania unsigned long long int
. How do you printf()
an unsigned long long int
?
Odpowiedzi:
Użyj długiego modyfikatora ll (el-el) z konwersją u (niepodpisaną). (Działa w systemie Windows, GNU).
źródło
long long
argumentówprintf
i używasz niewłaściwego formatu dla jednego z nich, powiedzmy%d
zamiast%lld
, to nawet argumenty wydrukowane po niewłaściwym mogą być całkowicie wyłączone (lub nawet spowodowaćprintf
awarię ). Zasadniczo zmienne argumenty są przekazywane do printf bez żadnych informacji o typie, więc jeśli łańcuch formatu jest niepoprawny, wynik jest nieprzewidywalny.Możesz spróbować użyć inttypes.h bibliotekę, która daje typów, takich jak
int32_t
,int64_t
,uint64_t
itd. Następnie można korzystać z jego makr, takich jak:To jest „gwarantowany”, aby nie dać ten sam problem, jak
long
,unsigned long long
itp, ponieważ nie trzeba zgadywać, ile bitów są w każdym typie danych.źródło
PRId64
,PRId32
zdefiniowane makra?inttypes.h
PRIu64
iPRIu32
dla liczb całkowitych bez znaku.inttypes.h
standardem? Nie byłobystdint.h
?leastX
ifastX
(które mogą być szersze niż wskazane).%d
-> dlaint
%u
-> dlaunsigned int
%ld
-> dlalong int
lublong
%lu
-> dlaunsigned long int
lublong unsigned int
lubunsigned long
%lld
-> dlalong long int
lublong long
%llu
-> dlaunsigned long long int
lubunsigned long long
źródło
W przypadku długiego (lub __int64) korzystania z MSVS należy użyć% I64d:
źródło
Wynika to z faktu, że% llu nie działa poprawnie w systemie Windows, a% d nie obsługuje 64-bitowych liczb całkowitych. Sugeruję użycie zamiast tego PRIu64, a przekonasz się, że jest również przenośny na Linuksa.
Spróbuj zamiast tego:
Wynik
źródło
int64_t
zamiast niego, ponieważ mogą istnieć pewne implementacje z długim długim większym niż długimW Linuksie jest,
%llu
aw Windowsie%I64u
Chociaż stwierdziłem, że nie działa w systemie Windows 2000, wydaje się, że jest tam błąd!
źródło
unsigned long long
że typ danych jest stosunkowo nowy (w tym czasie ze standardem C99), ale kompilatory C (w tym MinGW / GCC) wykorzystują stary środowisko uruchomieniowe Microsoft C, które obsługuje tylko specyfikację C89. Mam dostęp tylko do naprawdę starych i dość aktualnych dokumentów Windows API. Trudno więc powiedzieć dokładnie, kiedy pojawiło sięI64u
wsparcie. Ale to brzmi jak epoka XP.Skompiluj go jako x64 za pomocą VS2005:
źródło
Oprócz tego, co ludzie pisali lata temu:
main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]
printf("%llu\n", k);
Wtedy twoja wersja mingw nie ma domyślnie c99. Dodaj tę flagę kompilatora:
-std=c99
.źródło
Najwyraźniej nikt nie wymyślił rozwiązania wieloplatformowego * od ponad dziesięciu lat od [roku] 2008, więc dołączę moje 😛. Plz upvote. (Żartuję. Nie obchodzi mnie to.)
Rozwiązanie:
lltoa()
Jak używać:
Przykład PO:
W przeciwieństwie do
%lld
ciągu formatu wydruku, ten działa dla mnie pod 32-bitowym GCC w systemie Windows.*) Cóż, prawie na wielu platformach. W MSVC najwyraźniej potrzebujesz
_ui64toa()
zamiastlltoa()
.źródło
lltoa
.Niestandardowe rzeczy są zawsze dziwne :)
dla długiej, długiej części pod GNU to
L
,ll
lubq
a pod oknami uważam, że to
ll
tylkoźródło
Klątwa:
Wynik:
źródło
Jednym ze sposobów jest skompilowanie go jako x64 z VS2008
Działa to tak, jak można się spodziewać:
W przypadku kodu 32-bitowego musimy użyć poprawnego specyfikatora formatu __int64% I64u. Tak się staje.
Ten kod działa zarówno dla 32-bitowego, jak i 64-bitowego kompilatora VS.
źródło