How to turn on (literally) ALL of GCC's warnings?

C++GccWarningsCompiler WarningsGcc Warning

C++ Problem Overview


I would like to enable -- literally -- ALL of the warnings that GCC has. (You'd think it would be easy...)

  • You'd think -Wall might do the trick, but nope! Still need -Wextra.

  • You'd think -Wextra might do the trick, but nope! Not all of the warnings listed here (for example, -Wshadow) are enabled by this. And I still have no idea if this list is comprehensive.

How do I tell GCC to enable (no if's, and's, or but's!) all the warnings it has?

C++ Solutions


Solution 1 - C++

You can't.

The manual for GCC 4.4.0 is only comprehensive for that version, but it does list all the possible warnings for 4.4.0. They're not all on the page you link to though, for instance some language-specific options are on the pages for C++ options or Obj-C options. To find them all you're better off looking at the Options Summary

Turning on everything would include -Wdouble-promotion which is only relevant on CPUs with a 32-bit single-precision floating-point unit which implements float in hardware, but emulates double in software. Doing calculations as double would use the software emulation and be slower. That's relevant for some embedded CPUs, but completely irrelevant for modern desktop CPUs with hardware support for 64-bit floating-point.

Another warning that's not usually useful is -Wtraditional, which warns about perfectly well formed code that has a different meaning (or doesn't work) in traditional C, e.g. "string " "concatenation", or ISO C function definitions! Do you really care about compatibility with 30 year old compilers? Do you really want a warning for writing int inc(int i) { return i+1; } ?

I think -Weffc++ is too noisy to be useful, it's based on the outdated first edition of Effective C++ and warns about constructs which are perfectly valid C++ (and for which the guidelines changed in later editions of the book.) I don't want to be warned that I haven't initialized a std::string member in my constructor; it has a default constructor that does exactly what I want, why should I write m_str() to call it? The -Weffc++ warnings that would be helpful are too difficult for the compiler to detect accurately (giving false negatives), and the ones that aren't useful, such as initializing all members explicitly, just produce too much noise, giving false positives.

Luc Danton provided a great example of useless warnings from -Waggregate-return that almost certainly never makes sense for C++ code.

i.e. you don't really want all warnings, you just think you do.

Go through the manual, read about them, decide which you might want to enable, try them. Reading your compiler's manual is a Good ThingTM anyway, taking a short cut and enabling warnings you don't understand is not a very good idea, especially if it's to avoid having to RTFM.

Anyone who just turns on everything is probably either doing so because they're clueless because or a pointy-haired boss said "no warnings."

Some warnings are important, and some aren't. You have to be discriminating or you mess up your program. Consider, for instance, -Wdouble-promotion. If you're working on an embedded system you might want this; if you're working on a desktop system you probably don't. And do you want -Wtraditional? I doubt it.

Edit: See also -Wall-all to enable all warnings which is closed as WONTFIX.

Edit 2: in response to DevSolar's complaint about makefiles needing to use different warnings depending on compiler version, if -Wall -Wextra isn't suitable then it's not difficult to use compiler-specific and version-specific CFLAGS:

compiler_name := $(notdir $(CC))
ifeq ($(compiler_name),gcc)
compiler_version := $(basename $(shell $(CC) -dumpversion))
endif
ifeq ($(compile_name),clang)
compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}')
endif
# ...
wflags.gcc.base := -Wall -Wextra
wflags.gcc.4.7 := -Wzero-as-null-pointer-constant
wflags.gcc.4.8 := $(wflags.gcc.4.7)
wflags.clang.base := -Wall -Wextra
wflags.clang.3.2 := -Weverything
CFLAGS += $(wflags.$(compiler_name).base) $(wflags.$(compiler_name).$(compiler_version))

Solution 2 - C++

I would agree with the previous answers that it is probably not beneficial to enable literally all warnings, however GCC does provide a reasonably convenient way to achieve this. The command

gcc -Q --help=warning

provides a list of all supported warning options with information on whether they are active. This can by the way be used to find out which options are (not) enabled by e.g. -Wall and -Wextra

gcc -Wall -Wextra -Q --help=warning

To enable all the warnings you can use some regex to extract the command line parameters

gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n'

For my current GCC this gives:

> -Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optimizations -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-redefined -Wc++-compat -Wc++0x-compat -Wc++14-compat -Wc-binding-type -Wc90-c99-compat -Wc99-c11-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditionally-supported -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration-after-statement -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declarations -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion -Weffc++ -Wempty-body -Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signedness -Wformat-y2k -Wformat-zero-length -Wfree-nonheap-object -Wfunction-elimination -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer-types -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversion -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-truncation -Wliteral-suffix -Wlogical-not-parentheses -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Wmissing-prototypes -Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-declaration -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-conversions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty-assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-compare -Wsign-promo -Wsized-deallocation -Wsizeof-array-argument -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-selector-match -Wsuggest-attribute=const -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-lifetime -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas -Wunsafe-loop-optimizations -Wunsuffixed-float-constants -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-dummy-argument -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wuse-without-only -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvirtual-move-assign -Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant -Wzerotrip -frequire-return-statement

This can now be used to call the GCC, i.e.

gcc $(gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n')

Note however that this results in warnings due to some warning options only being available for certain languages (e.g. C++). These could be avoided by using some more regex to only include the options allowed for the current language or by adding an appropriate -Wno-whatever at the end of the call.

Solution 3 - C++

It's simply impossible to program with all warnings enabled (unless you are going to ignore them, but then, why bother?). For example, let's assume you use following set of flags: -Wstrict-prototypes -Wtraditional.

Even with two warnings enabled, the following program would complain.

/tmp $ cat main.c 
int main(int argc, char **argv) {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c: In function ‘main’:
main.c:1:5: warning: traditional C rejects ISO C style function definitions [-Wtraditional]
 int main(int argc, char **argv) {
     ^

You may think "well, I'm going to use old style prototypes then". Nope, this won't work.

/tmp $ cat main.c 
int main(argc, argv)
    int argc;
    char **argv;
{
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

And no, not specifying any prototype is also wrong, as the compiler will also complain.

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 int main() {
     ^

If you define any functions inside your program, you cannot use all flags, because the compiler will complain about any imaginable function definition.

For C++, this is possible (the -Wtraditional flag doesn't exist), and very simple programs can be compiled. To enable all warnings, use following list of warnings (probably some warnings are duplicated, because I didn't bother to filter warnings enabled by -Wall).

-Wabi -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Weffc++ -Wstrict-null-sentinel -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds -Wno-attributes -Wno-builtin-macro-redefined -Wc++0x-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment -Wconversion -Wcoverage-mismatch -Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization -Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wignored-qualifiers -Winit-self -Winline -Wno-int-to-pointer-cast -Wno-invalid-offsetof -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wlong-long -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wno-mudflap -Wno-multichar -Wnonnull -Wno-overflow -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wsign-conversion -Wstack-protector -Wstrict-aliasing=1 -Wstrict-overflow=5 -Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand -Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wno-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings

Solution 4 - C++

Someone has created a set of tools for determining the complete set of warnings for a given GCC or Clang version.

For GCC, copying from the full list of warnings provided by this tool for your compiler version appears to be the only way to ensure that all warnings are turned on, since (unlike Clang) GCC does not provide -Weverything.

The tool appears to parse the actual c.opt file in the GCC source code, so its results should be definitive.

The repository also contains text files with the warning lists generated for most GCC and Clang versions (currently Clang 3.2 through 3.7 and GCC 3.4 through 5.3).

https://github.com/barro/compiler-warnings

Solution 5 - C++

Gcc 4.3+ now has -Q --help=warnings, you can even specify --help=warnings,C to just print out the C related warnings.

I just wrote a m4 module to take advantage of this (also supports clang's -Weverything), see wget_manywarnings.m4

How to use it is pretty simple, basically the module turns every warn flag on. And you remove warnings as needed - some are really very verbose. Example: configure.ac

If you don't use autotools, you'll find the code to turn on all disabled warnings in the m4 module, which basically is the gcc call piped through awk:

flags="-Wall -Wextra -Wformat=2 "$(gcc -Wall -Wextra -Wformat=2 -Q --help=warning,C|awk '{ if (($2 == "[disabled]" || $2 == "") && $1!~/=/ && $1~/^-W/&& $1!="-Wall") print $1 }'

Solution 6 - C++

From this page:

> Note that some warning flags are not implied by -Wall. Some of them > warn about constructions that users generally do not consider > questionable, but which occasionally you might wish to check for; > others warn about constructions that are necessary or hard to avoid in > some cases, and there is no simple way to modify the code to suppress > the warning. Some of them are enabled by -Wextra but many of them > must be enabled individually.

I guess the question is which ones? Perhaps you could grep that page for all lines beginning with -W, and get a complete list of warning flags. Then compare those with the lists under -Wall and -Wextra. There is also -Wpedantic, though you are obviously wanting to be even more pedantic still =)

Solution 7 - C++

> And I still have no idea if this list is comprehensive.

It probably is, but the only list that is 100% comprehensive is the actual source for the compiler. However, GCC is big! And I don't know if all command-line parameters are collected in one place or spread out over several source files. Also note that some warnings are for the pre-processor, some for the actual compiler and some for the linker (which is a completely separate program, and found in the binutils package) so they most likely are spread out.

Solution 8 - C++

I gathered information from the other postings and one-by-one tested the warnings in the test for a C++ library.

Using the list from @Haatschii and his/her method of getting the full list for GCC 11:

gcc -Wall -Wextra -Wpedantic -Q --help=warning

Of all these warnings some do not apply to C++, so here it is a list of warnings and some minimal comments that work for the tests of my C++ project.

Take into account, that:

  1. Some of these warnings are by default already turned on without adding any option.
  2. I don't claim to know what some warnings actually mean.
  3. I don't recommend using or not using any particular warning.
  4. Some are commented, that doesn't mean anything. Comment or uncomment them as you need. (I commented the ones that were not useful for my project).
  5. Some will not work on GCC 10.
  6. The list is given AS-IS, it may contain errors or typos.

The list is basically order in alphabetical order, with some minimal bunching to save vertical space. As a bonus is formatted for use in a CMake project.

Now the list:

		target_compile_options(
			target
			PRIVATE
				$<CXX_COMPILER_ID:GNU>:
					-Werror
					-Wall
					-Wextra  # (activates -Wunknown-pragmas)
					-Wextra-semi
					-Wpedantic
					# -Wabi=13 -Wabi-tag (maybe important when linking with very old libraries)
					-Waddress -Waddress-of-packed-member
					# -Waggregate-return (disallow return classes or structs, seems a C-compatibility warning)
					-Waggressive-loop-optimizations
					-Walloc-zero  # -Walloc-size-larger-than=
					-Walloca  # -Walloca-larger-than=
					-Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak -Wanalyzer-mismatching-deallocation -Wanalyzer-null-argument -Wanalyzer-null-dereference -Wanalyzer-possible-null-argument -Wanalyzer-possible-null-dereference -Wanalyzer-shift-count-negative -Wanalyzer-shift-count-overflow -Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-array-index -Wanalyzer-too-complex -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame -Wanalyzer-write-to-const -Wanalyzer-write-to-string-literal
					-Warith-conversion
					-Warray-bounds -Warray-parameter #  -Warray-bounds=<0,2> -Warray-parameter=<0,2> 
					-Wattribute-warning -Wattributes
					-Wbool-compare -Wbool-operation
					-Wbuiltin-declaration-mismatch -Wbuiltin-macro-redefined
					-Wc++0x-compat -Wc++14-compat -Wc++17-compat -Wc++1z-compat -Wc++20-compat -Wc++2a-compat
					-Wcannot-profile
					-Wcast-align -Wcast-align=strict -Wcast-function-type -Wcast-qual
					-Wcatch-value  # -Wcatch-value=<0, 3>
					-Wchar-subscripts -Wclobbered -Wcomment  # (same as -Wcomments)
					-Wconditionally-supported
					-Wconversion -Wconversion-null
					-Wcoverage-mismatch -Wcpp 
					# -Wctad-maybe-unsupported  (make ctad explicitly necessary)
					-Wctor-dtor-privacy
					-Wdangling-else -Wdate-time
					-Wdelete-incomplete -Wdelete-non-virtual-dtor
					-Wdeprecated -Wdeprecated-copy -Wdeprecated-copy-dtor -Wdeprecated-declarations -Wdeprecated-enum-enum-conversion -Wdeprecated-enum-float-conversion
					-Wdisabled-optimization -Wdiv-by-zero -Wdouble-promotion
					-Wduplicated-branches -Wduplicated-cond
					# -Weffc++ (doesn't allow some advanced techniques, such as CRTP)
					-Wempty-body -Wendif-labels
					-Wenum-compare -Wenum-conversion
					-Wexpansion-to-defined
					-Wexceptions
					# -Wextra (see above)
					-Wfloat-conversion # -Wfloat-equal (disallows float equality)
					-Wformat-truncation -Wformat=2 -Wformat-diag -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signedness -Wformat-truncation -Wformat-y2k -Wformat-zero-length  # -Wformat-overflow=<0,2>
					-Wframe-address  # -Wframe-larger-than=<byte-size>
					-Wfree-nonheap-object -Whsa -Wif-not-aligned
					-Wignored-attributes -Wignored-qualifiers
					-Wimplicit-fallthrough#=3  # -Wimplicit-fallthrough=<0,5>
					-Winit-self
					# -Winline
					-Wint-in-bool-context -Wint-to-pointer-cast
					-Winvalid-imported-macros
					-Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch
					-Wignored-qualifiers
					# -Wlarger-than=<byte-size>  # (disallow large objects types? in executable)
					-Wliteral-suffix
					-Wlogical-not-parentheses -Wlogical-op
					-Wlong-long -Wlto-type-mismatch -Wmain -Wmaybe-uninitialized
					-Wmemset-elt-size -Wmemset-transposed-args
					-Wmisleading-indentation
					-Wmismatched-dealloc -Wmismatched-new-delete -Wmismatched-tags
					-Wmissing-attributes -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wmissing-profile
					-Wmultichar
					# -Wmultiple-inheritance (disallows composition by inheritance)
					-Wmultistatement-macros
					# -Wnamespaces (disallows use of namespaces, seems a C-tool)
					-Wnarrowing
					-Wnoexcept -Wnoexcept-type
					-Wnormalized  #=nfc -Wnormalized=[none|id|nfc|nfkc]
					-Wnon-template-friend
					-Wnon-virtual-dtor
					-Wnonnull -Wnonnull-compare -Wnull-dereference
					-Wodr -Wold-style-cast -Wopenmp-simd -Woverflow
					-Woverlength-strings -Woverloaded-virtual
					-Wpacked -Wpacked-bitfield-compat -Wpacked-not-aligned
					# -Wpadded (disallows structs that need padding for alignment)
					-Wparentheses
					# -Wpedantic (see above)
					-Wpessimizing-move -Wplacement-new  #=1  -Wplacement-new=<0,2>
					-Wpmf-conversions
					-Wpointer-arith -Wpointer-compare
					-Wpragmas -Wprio-ctor-dtor -Wpsabi
					-Wrange-loop-construct -Wredundant-decls -Wredundant-move -Wredundant-tags -Wregister
					-Wreturn-local-addr -Wreturn-type
					-Wrestrict -Wreorder
					-Wscalar-storage-order -Wsequence-point
					-Wshadow -Wshadow-compatible-local -Wshadow-local -Wshadow=compatible-local -Wshadow=local
					-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value -Wshift-overflow  #=1 -Wshift-overflow=<0,2>
					-Wsign-compare -Wsign-conversion -Wsign-promo
					-Wsized-deallocation
					-Wsizeof-array-argument -Wsizeof-array-div -Wsizeof-pointer-div -Wsizeof-pointer-memaccess
					-Wstack-protector  # -Wstack-usage=<byte-size> 
					-Wstrict-aliasing  #=3  -Wstrict-aliasing=<0,3>
					-Wstrict-null-sentinel  #=1  -Wstrict-overflow=<0,5>
					-Wstrict-overflow  #=1  -Wstrict-overflow=<0,5>
					-Wstring-compare
					-Wstringop-overflow  #=2  -Wstringop-overflow=<0,4>
					-Wstringop-overread -Wstringop-truncation
					-Wsubobject-linkage
					-Wsuggest-attribute=const -Wsuggest-attribute=format -Wsuggest-attribute=malloc -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure -Wsuggest-final-methods -Wsuggest-final-types
					-Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wswitch-outside-range -Wswitch-unreachable
					-Wsync-nand -Wsynth
					# -Wsystem-headers (expects system headers to be warning-compliant which they are not)
					-Wtautological-compare
					# -Wtemplates (disallows templates, C-tool)
					-Wtrampolines -Wtrigraphs -Wtsan
					-Wtype-limits -Wundef -Wuninitialized
					-Wno-unknown-pragmas  # (see above) -Wunknown-pragmas (other compilers need their own pragmas for their warnings)
					-Wunreachable-code -Wunsafe-loop-optimizations
					-Wunused -Wunused-parameter -Wunused-but-set-variable 
					# -Wunused-const-variable  #=2
					-Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable
					-Wuseless-cast
					-Wvarargs -Wvariadic-macros -Wvector-operation-performance -Wvexing-parse -Wvirtual-inheritance -Wvirtual-move-assign
					-Wvla -Wvla-parameter
					-Wvolatile -Wvolatile-register-var
					-Wwrite-strings
					-Wzero-as-null-pointer-constant
				>
		)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser541686View Question on Stackoverflow
Solution 1 - C++Jonathan WakelyView Answer on Stackoverflow
Solution 2 - C++HaatschiiView Answer on Stackoverflow
Solution 3 - C++Konrad BorowskiView Answer on Stackoverflow
Solution 4 - C++Kyle StrandView Answer on Stackoverflow
Solution 5 - C++rockdabootView Answer on Stackoverflow
Solution 6 - C++paddyView Answer on Stackoverflow
Solution 7 - C++Some programmer dudeView Answer on Stackoverflow
Solution 8 - C++alfCView Answer on Stackoverflow