How to fix C++ warning of implicit conversion? - c++

I am just getting started in C++.
I am trying to get the first three characters of the string 'str', and compare it to a known string, say, 'knownString'.
To do that, I wrote this line of code:
if (str.substr(start, 3) == knownString)
where 'start' is an integer I declared before.
But I keep getting this warning message:
warning: implicit conversion changes signedness: 'int' to
'std::__cxx11::basic_string,**
**std::allocator >::size_type' (aka 'unsigned int')
Does anyone knows what I can add or I missed in this statement to fix this?

You can:
Either 1. make the conversion explicit:
str.substr(static_cast<std::string::size_type>(start), 3)
Or 2. not make a conversion in the first place:
std::string::size_type start;
Or 3. ask compiler to not warn about it:
g++ compilation arguments -Wno-sign-conversion
I recommend option 2.

This warning is triggered by the -Wsign-conversion switch, detecting that you're taking a signed variable and converting it to an unsigned variable, in a way that may change the value.
It doesn't do it for positive literals, where the conversion obviously doesn't change the value, because that would be pointless and really annoying. You'll get it for a negative literal like -5.
(Technically, this is the literal 5 with the unary negation operator applied, not a "negative literal"!).
For named variables it can't really predict what the value would be, so errs on the side of caution.
You should make your variable start have type size_t.

Related

Why write `!!x`, when `x` will do? [duplicate]

This question already has answers here:
Double Negation in C++
(14 answers)
What is the usage of "!!" (negating twice)? [duplicate]
(3 answers)
Confused by use of double logical not (!!) operator [duplicate]
(5 answers)
Closed 2 years ago.
I often see experienced programmers write !!x, even though the expected expression is a Boolean (i.e., zero or not zero) and not an integer.
For example, a line from boost:
BOOST_ASSERT(!!p); // where `p` is a pointer
What's the point of !!p when just p will do?
What I understand by a Boolean parameter is an expression converted to a value of integral type, and the value is compared against zero, explicitly or implicitly (with if or its ternary operator equivalent).
Thus, anything that takes a Boolean and expects only 0 or 1 is wrongly implemented, if my understanding of Boolean is correct.
For clarification: it's obvious that ! converts to bool; the question is explicitly asking for why.
By default, BOOST_ASSERT(expr) expands to assert(expr). That C++ assert function takes a scalar argument, not bool. Thus, your statement, "the expected expression is a boolean," is not correct.
Classes in C++ can implement operator bool(); the basic_stream classes are examples of such: assert(std::cin) will not work. The !! operator forces the use of std::cin::operator bool(), and bool after !! will be evaluated to int 0 or 1. This is shorter than assert(bool(std::cin)).
If I were a boost author, I would expand BOOST_ASSERT(expr) to assert(!!(expr)) - as is done for ( BOOST_LIKELY(!!(expr)) ? ((void)0) ).
Closely related to the question
Warnings.
Some compilers issue warnings.
Overflow of the integer storing the Boolean.
I'll just quote the comment mentioning the behaviour
The compiler would treat the values the same either way if it's only used as an operand to an if or &&, but using !! may help on some compilers if if (!!(number & mask)) gets replaced with bit triggered = !!(number & mask); if (triggered); on some embedded compilers with bit types, assigning e.g. 256 to a bit type will yield zero. Without the !!, the apparently-safe transformation (copying the if condition to a variable and then branching) won't be safe.
Related
Some consider defining operator bool() to be "unsafe". And to have an idiomatical way to convert to bool, they define bool operator !().
So writing !!obj is to support such users. And it doesn't even hurt to do so!

Failed to initialize typeless char in f77

I tried to assign the horizontal table
character*(*) argz(*),tab*1
data tab /Z'09'/
Compiling with both f77 and gfortran gave
data tab /Z'09'/
1 Error: Incompatible types in DATA statement at (1); attempted conversion of INTEGER(16) to CHARACTER(1)
As commented, if you simply want an ASCII tab character then ACHAR(9) provides such a thing. However, there are other aspects to this question which makes it much more general.
A literal constant such as Z'09' is known as a BOZ constant. This represents a series of bits.
Use of a BOZ constant is quite restricted in the Fortran standards (becoming less so over time) and many compilers allow other uses beyond the standard as extensions. For example, a BOZ constant in a Fortran-compliant program may appear in only a small number of places. Some compilers may allow them to appear any way a literal constant may.
The Oracle documentation you point to in a comment even has that compiler allowing the type of the expression assumed from its use.
With your compilers, trying
character tab
data tab /Z'09'/
fails. The gfortran message says that it is taking the constant to be of type integer(16) which (correctly) cannot be converted to character. Further, according to the Fortran standard, any data object defined by a BOZ constant in a data statement must be an integer.
We know that
character :: tab=ACHAR(9) ! This is also explicit initialization.
has the desired effect, but can we do this with a BOZ constant?
You point to the gfortran documentation of achar and say that it doesn't refer to the argument being hexadecimal. It says there that I must be integer. A BOZ constant isn't an integer, so achar(Z'09') isn't allowed by Fortran. [Although this is actually accepted by gfortran and other compilers.]
A fully standard compliant approach is
character :: tab=ACHAR(INT(Z'09'))
as int accepts these constants, returning an integer (which is in turn acceptable to achar).
The constant expression achar(int(z'09')) may not itself appear in a data statement like
character tab
data tab /ACHAR(INT(Z'09'))/ ! No...
as it isn't a constant. However, we could have
character, parameter :: tabconst=ACHAR(INT(Z'09'))
character tab
data tab /tabconst/ ! tabconst is a (named) constant

Is Repeated Assignment Defined for get_time?

I was working on this answer. And I ran into a conundrum: scanf has an assignment suppressing '*':
If this option is present, the function does not assign the result of the conversion to any receiving argument
But when used in get_time the '*' gives a run-time error on Visual Studio, libc++, and libstdc++: str >> get_time(&tmbuf, "%T.%*Y") so I believe it's not supported.
As such I chose to ignore input by reading into tmbuf.tm_year twice:
str >> get_time(&tmbuf, "%H:%M:%S.%Y UTC %b %d %Y");
This works and seems to be my only option so far as get_time goes since the '*' isn't accepted. But as we all know, just because it works doesn't mean it's defined. Can someone confirm that:
It is defined to assign the same variable twice in get_time
The stream will always be read left-to-right so the 1stincidence of %Y will be stomped, not the 2nd
The standard specifies the exact algorithm of processing the format string of get_time in 22.4.5.1.1 time_get members. (time_get::get is what eventually gets called when you do str>>get_time(...)). I quote the important parts:
The function starts by evaluating err = ios_base::goodbit. It then enters a loop, reading zero or more characters from s at each iteration. Unless otherwise specified below, the loop terminates when the first of the following conditions holds:
(8.1) — The expression fmt == fmtend evaluates to true.
skip boring error-handling parts
(8.4) — The next element of fmt is equal to ’%’, optionally followed by a modifier character, followed by a conversion specifier character, format, together forming a conversion specification valid for the ISO/IEC 9945 function strptime. skip boring error-handling parts the function evaluates s = do_get(s, end, f, err, t, format, modifier) skip more boring error-handling parts the function increments fmt to point just past the end of the conversion specification and continues looping.
As can be seen from the description, the format string is processed strictly sequentially left to right. There's no provision to handle repeating conversion specifications specially. So the answer must be yes, what you have done is it is well defined and perfectly legal.

Is the expression 'ab' == "ab" true in C++

My question sounds probably quite stupid, but I have to answer it while preparing myself to my bachelor exam.
So, what do you think about such an expression 'ab' == "ab" in C++? Is this not true or simply not legal and compiling error? I have googled a little and get to know that 'ab' is in type int and "ab" of course not...
I have to regard not what compilator says but what says formal description of language..
It definitely generates a warning, but by default, gcc compiles it.
It should normally be false.
That being said, it should be theoretically possible, of course depending on the platform you're running this on, to have the compile-time constant "ab" at a memory location whose address is equal in numerical value to the numerical value of 'ab', case in which the expression would be true (although the comparison is of course meaningless).
In both C and C++ expression 'ab' == "ab" is invalid. It has no meaning. Neither language allows comparing arbitrary integral values with pointer values. For this reason, the matter of it being "true" or not does not even arise. In order to turn it into a compilable expression you have to explicitly cast the operands to comparable types.
The only loophole here is that the value of multi-char character constant is implementation-defined. If in some implementation the value of 'ab' happens to be zero, it can serve as a null-pointer constant. In that case 'ab' == "ab" becomes equivalent to 0 == "ab" and NULL == "ab". This is guaranteed to be false.
It is going to give you a warning, but it will build. What it will do is compare the multibyte integer 'ab' with the address of the string literal "ab".
Bottom line, the result of the comparison won't reflect the choice of letters being the same or not.
The Standard has absolutely nothing to say about comparing an integral type with a pointer. All it says is the following (in section 5.9):
The operands shall have arithmetic, enumeration, or pointer type, or
type std::nullptr_t...
It then goes into a detailed description on what it means to compare two pointers, and mentions comparing two integers. So my interpretation of the lack of specification would be "whatever the compiler writer decides", which is either an error or a warning.
Lets consider this to parts in simple C, the 'c' is a simple char if you want to manipulate strings you will have to use array of chars, as a result 'ca' shouldn't work the way you expect, and in c++ this stuff is still valid. If you want to use Strings you will have to use String class which isn't a raw type. And all what it does is a class with methods and type def's so you handle chars of arrays easier. As result even the C-style-string and the array of chars are different stuff, as result 'ab' == "ab" is not going to give a valid boolean respond . It's like trying to compare an int to a string. So, this comaprison will most likely throw an error.

Using MSVC preprocessor 'charizing' operator in Clang

I've got the following code that someone working on MSVC has given to me:
#define MAP1(x, y) map[#x] = ##y;
I'm on Xcode, using Clang, and from various google searches I've found that this is known as a 'charizing operator', and is specific to MSVC's preprocessor. Is there a way of emulating the functionality of this operator while using Clang? I've tried removing the # but got the following error message:
Assigning to 'int' from incompatible type 'const char[2]'
Would an explicit cast to 'int' work or is the charizing operator doing something different?
The stringizing operator (standard C++) converts a into "a", so the charizing operator sounds like it turns a into 'a'. You can, in the simple cases, get 'a' from "a" by taking the first character.
#define MAP1(x, y) map[#x] = static_cast<const char(&)[2]>(#y)[0];
The static_cast to const char(&)[2] ensures you get a compile-time error if you don't get a string of length 1, which is two characters if you count the trailing '\0'. A plain #y[0] would silently take the first character, regardless of the string's length.
Did you try something like #y[0]? Basically, "stringify y and take the first char" :-)
Other than that, since from the looks of it the generated statements are executed at runtime anyway, you can just stringify y, pass it to a function and have that function return the right thing.