%llx format specifier: invalid warning? - c++

Edited to remove the first warning
The following code works as expected in g++ 4.4.0 under mingw32:
#include <cstdio>
int main()
{
long long x = 0xdeadbeefc0defaceLL ;
printf ("%llx\n", x) ;
}
But if I enable all warnings with -Wall, it says:
f.cpp: In function 'int main()':
f.cpp:5: warning: unknown conversion type character 'l' in format
f.cpp:5: warning: too many arguments for format
It's the same with %lld. Is this fixed in newer versions?
Edited again to add:
The warning doesn't go away if I specify -std=c++0x, even though (i) long long is a standard type, and (ii) %lld and %llx seem to be officially supported. For instance, from 21.5 Numeric conversions para 7:
Each function returns a string object holding the character representation of the value of
its argument that would be generated by calling sprintf(buf, fmt, val) with a format specifier of
"%d", "%u", "%ld", "%lu", "%lld", "%llu", "%f", "%f", or "%Lf", respectively, where buf designates
an internal character buffer of sufficient size.
So this is a bug, surely?

long long x = 0xdeadbeefc0defaceLL; // note LL in the end
And there is no ll length specifier for printf. The best you can get is:
printf ("%lx\n", x); // l is for long int
I've tested your sample on my g++, it compiles without errors even without -std=c++0x flag:
~$ g++ -Wall test.cpp
~$ g++ --version
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
So, yes, this fixed in newer versions.

For first warning I can say that you must use 0xdeadbeefc0defaceLL instead of 0xdeadbeefc0deface. After that other warnings may pass also.

I get the same warning compiling C using windows/mingw32.
warning: unknown conversion type character 'l' in format
So yes, probably a compiler/platform specific bug.

It's a Mingw-specific issue, because it calls the native Windows runtime for certain things, including this. See this answer.
%I64d works for me. In the answer linked above there is a more portable albeit less readable solution as well.

Related

What does this line of code mean

There is lots of changes in C++ 11 and afterwards. And I just came across this line of code, I thought I created an empty array which defaults to zero and I just added an element in the beginning of the array which is 99. But it prints 42. I am really confused.
int a1 []{};
a1[0] = 99;
cout<<"a1 is " << a1[0];
Console:
a1 is 42
This is not standard C++ program. Zero size arrays are not allowed in C & C++. You should use -pedantic-errors command line option if you are using g++ & clang++ compiler to strictly confirm to the standard & disable any compiler extensions.
See live demo here. Clang++ says
source_file.cpp:7:14: error: zero size arrays are an extension [-Werror,-Wzero-length-array]
int a1 []{};
^
1 error generated.
If you compile that code with g++ -std=c++11 -pedantic -W -Wall, you will get an error:
test.cpp:6:12: error: zero-size array ‘a1’
int a1 []{};
This code is invalid.
As an extension, some compilers offer (in a less compliant mode) zero sized arrays. In which case, you simply read/wrote the byte adjacent to the empty array, which just so happened to not crash...

Capitalize first letter of string

I am trying to capitalize the first character of a std::string, using the same method mentioned here. For example for the following program
#include <cctype>
#include <iostream>
#include <string>
int main()
{
std::string name = "foobar";
name[0] = std::toupper(name[0]);
std::cout << name;
}
I am expecting the output to be
Foobar
When I compile this online (using GCC 4.9.2) I get the correct output without any warnings. However, when I compile the same code in Visual Studio 2013, I get a warning during the assignment back from toupper
warning C4244: '=' : conversion from 'int' to 'char', possible loss of data
Is the above method valid according to the C++ standard or is the warning correct? Otherwise is this just a false warning by Visual Studio?
The warning is correct as far the types go; the type of std::toupper as defined in the standard is:
int toupper( int ch );
Mostly because it's a remnant from the dark C ages (the cctype header is a hint at that).
However, this is just a part of the story. There's another toupper residing in the locale header:
template< class charT >
charT toupper( charT ch, const locale& loc );
This one shouldn't give you any warnings. If you're not sure what locale to provide, std::locale() will give you the default one.
std::toupper comes from the C standard, not C++, and has an annoying interface in that it takes and returns an int not a char. Using static_cast<char>(std::toupper(name[0])) will suit you.
The warning is correct, compiler will implicitly cast from int to char but this might cause lost of data in some cases. To see warning under gcc you need to add -Wconversion compiler option. Which will generate:
main.cpp: In function 'int main()':
main.cpp:8:13: warning: conversion to '__gnu_cxx::__alloc_traits<std::allocator<char> >::value_type {aka char}' from 'int' may alter its value [-Wconversion]
name[0] = std::toupper(name[0]);
^
Foobar
Why it is not present when -Wall is set, read here:
https://gcc.gnu.org/wiki/NewWconversion
Why isn't Wconversion enabled by -Wall or at least by -Wextra?
Implicit conversions are very common in C. This tied with the fact
that there is no data-flow in front-ends (see next question) results
in hard to avoid warnings for perfectly working and valid code.
Wconversion is designed for a niche of uses (security audits, porting
32 bit code to 64 bit, etc.) where the programmer is willing to accept
and workaround invalid warnings. Therefore, it shouldn't be enabled if
it is not explicitly requested.

How to silence long long integer constant warning from GCC

I have some code using large integer literals as follows:
if(nanoseconds < 1'000'000'000'000)
This gives the compiler warning integer constant is too large for 'long' type [-Wlong-long]. However, if I change it to:
if(nanoseconds < 1'000'000'000'000ll)
...I instead get the warning use of C++11 long long integer constant [-Wlong-long].
I would like to disable this warning just for this line, but without disabling -Wlong-long or using -Wno-long-long for the entire project. I have tried surrounding it with:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlong-long"
...
#pragma GCC diagnostic pop
but that does not seem to work here with this warning. Is there something else I can try?
I am building with -std=gnu++1z.
Edit: minimal example for the comments:
#include <iostream>
auto main()->int {
double nanoseconds = 10.0;
if(nanoseconds < 1'000'000'000'000ll) {
std::cout << "hello" << std::endl;
}
return EXIT_SUCCESS;
}
Building with g++ -std=gnu++1z -Wlong-long test.cpp gives test.cpp:6:20: warning: use of C++11 long long integer constant [-Wlong-long]
I should mention this is on a 32bit platform, Windows with MinGW-w64 (gcc 5.1.0) - the first warning does not seem to appear on my 64bit Linux systems, but the second (with the ll suffix) appears on both.
It seems that the C++11 warning when using the ll suffix may be a gcc bug. (Thanks #praetorian)
A workaround (inspired by #nate-eldredge's comment) is to avoid using the literal and have it produced at compile time with constexpr:
int64_t constexpr const trillion = int64_t(1'000'000) * int64_t(1'000'000);
if(nanoseconds < trillion) ...

C++ Type Check in Functions ignored (required double, provided int)

I have the following code
#include <iostream>
using namespace std;
int dmult(int a, int b){
return 2*a*b;
}
int main(void)
{
double a = 3.3;
double b = 2;
int c = dmult(a,b);
cout << c << endl;
return 0;
}
It compiles with MinGW without problems. The result is (as I thought) false. Is it a problem of the compiler that there is no warning, that a function expecting integers, but fed with doubles, can compile without warning even if the input type is wrong? Does it mean that C++ ignores the input type of a function? Shouldn't it realize that the function arguments have the wrong type?
double's are implicitly convertible to ints (and truncated), and the compiler is not forced by the standard to emit a warning (it tries its best to perform the conversion whenever possible). Compile with -Wconversion
g++ -Wconversion program.cpp
and you'll get your warning:
warning: conversion to 'int' from 'double' may alter its value [-Wfloat-conversion]
The typical warning flags -Wall -Wextra don't catch it since many times it is the programmer's intention to truncate double's to int's.
Live example here.
c++ automatically casts floats and doubles to integer literals by truncating them. so 3.3 becomes 3 when you call dmult(3.3,2)

gcc 4.9.2 bug in -Werror=sizeof-pointer-memaccess?

#include <string.h>
void test(char charArray [100])
{
strncpy(charArray, "some text", sizeof(charArray));
}
int main()
{
char charArray [100];
test(charArray);
// EDIT: According to comment from P0W I added this line - where is the difference?
strncpy(charArray, "some text", sizeof(charArray)); // compiles OK
}
Compiled with gcc 4.9.2 on SLES 11 SP2 with this command line g++ gcc-warning-bug-2.cpp -Wall -Wextra -c -Werror I get this warning. Due the -Werror flag I cannot compile the project:
gcc-warning-bug-2.cpp: In function ‘void test(char*)’:
gcc-warning-bug-2.cpp:5:40: error: argument to ‘sizeof’ in ‘char* strncpy(char*, const char*, size_t)’ call is the same expression as the destination; did you mean to provide an explicit length? [-Werror=sizeof-pointer-memaccess]
strncpy(charArray, "some text", sizeof(charArray));
^
cc1plus: all warnings being treated as errors
According to the actual gcc 4.9.2 documentation https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
-Wsizeof-pointer-memaccess
Warn for suspicious length parameters to certain string and memory built-in functions if the argument uses sizeof.
This warning warns e.g. about memset (ptr, 0, sizeof (ptr)); if ptr is not an array, but a pointer, and suggests a possible fix, or about memcpy (&foo, ptr, sizeof (&foo));. This warning is enabled by -Wall.
this should be compiled fine because charArray is an array!
Bug? Should I report it to GNU gcc developer team?
You fell straight into the trap.
In C, C++, Objective-C, Objective-C++, a parameter with a declaration that looks like "array of T" actually has type T*.
Your parameter charArray has a declaration that looks like "array of 100 chars", but the declaration is in fact "pointer to char".
Therefore, your third parameter to strncpy has a value of (most likely) 4 or 8, and not the 100 that you seem to expecct.
BTW. strncpy is highly dangerous the way you use it.