When you compile the following C++ source file in Visual Studio 2010 with warning level /W4 enabled
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
if (result = strcmp(str0, str1)) // line 11
{
printf("Strings are different\n");
}
}
you get the following warning
warning C4706: assignment within conditional expression
for line 11.
I want to suppress this warning exactly at this place. So I tried Google and found this page: http://msdn.microsoft.com/en-us/library/2c8f766e(v=VS.100).aspx
So I changed the code to the following - hoping this would solve the problem:
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
#pragma warning(push)
#pragma warning(disable : 4706)
if (result = strcmp(str0, str1))
#pragma warning(pop)
{
printf("Strings are different\n");
}
}
It didn't help.
This variant didn't help either:
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
int main()
{
int result;
#pragma warning(push)
#pragma warning(disable : 4706)
if (result = strcmp(str0, str1))
{
#pragma warning(pop)
printf("Strings are different\n");
}
}
To avoid one further inquiry: I cleaned the solution before each compilation. So this is probably not the fault.
So in conclusion: how do I suppress the C4706 exactly at this place?
Edit Yes, rewriting is possible - but I really want to know why the way I try to suppress the warning (that is documented officially on MSDN) doesn't work - where is the mistake?
Instead of trying to hide your warning, fix the issue it's complaining about; your assignment has a value (the value on the left side of the assignment) that can be legally used in another expression.
You can fix this by explicitly testing the result of the assignment:
if ((result = strcmp(str0, str1)) != 0)
{
printf("Strings are different\n");
}
In MSDN Libray: http://msdn.microsoft.com/en-us/library/2c8f766e(v=VS.100).aspx, There is the section as follows.
For warning numbers in the range 4700-4999, which are the ones
associated with code generation, the state of the warning in effect
when the compiler encounters the open curly brace of a function will
be in effect for the rest of the function. Using the warning pragma in
the function to change the state of a warning that has a number larger
than 4699 will only take effect after the end of the function. The
following example shows the correct placement of warning pragmas to
disable a code-generation warning message, and then to restore it.
So '#pragma warning' only works for an each function/method.
Please see the following code for more detail.
#include <cstdio> // for printf
#include <cstring> // for strcmp
char str0[] = "Hello";
char str1[] = "World";
#pragma warning(push)
#pragma warning( disable : 4706 )
void func()
{
int result;
if (result = strcmp(str0, str1)) // No warning
{
printf("Strings are different\n");
}
#pragma warning(pop)
}
int main()
{
int result;
if (result = strcmp(str0, str1)) // 4706 Warning.
{
printf("Strings are different\n");
}
}
The sane solution is to rewrite the condition to
if( (result = strcmp(str0, str1)) != 0 )
which will inform any C compiler that you really want to assign, and is almost certain to generate the same object code.
There is another solution which avoids the warning: the comma operator.
The main advantage here will be that you don't need parentheses so it's a bit shorter than the !=0 solution when your variable name is short.
For example:
if (result = strcmp(str0, str1), result)
{
printf("Strings are different\n");
}
There is a simple construction !! to cast a type to bool. Like this:
if (!!(result = strcmp(str0, str1)))
However, in some cases direct comparison != 0 might be more clear to a reader.
Related
Scenario
I have a C++ function which intakes a parameter as std::chrono::milliseconds. It is basically a timeout value. And, it is a default parameter set to some value by default.
Code
#include <iostream>
#include <chrono>
void Fun(const std::chrono::milliseconds someTimeout = std::chrono::milliseconds(100)) {
if (someTimeout > 0) {
std::cout << "someNumberInMillis is: " << someNumberInMillis.count() << std::endl;
}
}
int main() {
unsigned int someValue = 500;
Fun(std::chrono::milliseconds(someValue))
}
Issue
All of above is okay but, when I call Fun with a value then fails to compile and I get the following error:
No viable conversion from 'bool' to 'std::chrono::milliseconds' (aka
'duration >')
Question:
What am I doing wrong here? I want the caller of Fun to be explicitly aware that it is using std::chrono::milliseconds when it invokes Fun. But the compiler doesn't seem to allow using std::chrono::milliseconds as a parameter?
How use std::chrono::milliseconds as a default parameter?
Environment
Compiler used is clang on macOS High Sierra
With the other syntax errors fixed, this compiles without warnings in GCC 9:
#include <iostream>
#include <chrono>
void Fun(const std::chrono::milliseconds someNumberInMillis
= std::chrono::milliseconds(100))
{
if (someNumberInMillis > std::chrono::milliseconds{0}) {
std::cout << "someNumberInMillis is: " << someNumberInMillis.count()
<< std::endl;
}
}
int main()
{
unsigned int someValue = 500;
Fun(std::chrono::milliseconds(someValue));
}
In the following test case, the alternation of one alpha and a sequence bombs with a long error dump basically saying static assertion failed: The parser expects tuple-like attribute type. Intuitively, I expected the entire rule to produce a string but that's not what happens. I either have to change the left-side of the alternation to +alpha (making both sides vectors) or go the path of semantic actions, at least for the lone char in the alternation (append to _val). Or, change the lone left-side char_ to string. Anyways, I can't figure out what's the proper simple way of parsing a string as trivial as this, any hint is appreciated. TIA.
#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace grammar {
using x3::char_;
using x3::alpha;
using x3::xdigit;
const auto x =
x3::rule< struct x_class, std::string > { "x" } =
char_('/') > alpha >> *(alpha | (char_('#') > xdigit));
} // namespace grammar
int main () {
std::string input{ "/Foobar#F" }, attr;
auto iter = input.begin ();
if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
std::cout << attr << std::endl;
}
return 0;
}
I hate this behaviour too. Qi was much more natural in this respect.
I honestly don't always know how to "fix" it although
in this case it seems you can use raw[] - simplifying the grammar as well
sometimes it helps to avoid mixing operator> and operator>>
Here's what I'd do for your grammar:
Live On Coliru
#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
namespace grammar {
const auto x =
x3::rule<struct x_class, std::string> { "x" } =
x3::raw [ '/' > x3::alpha >> *(x3::alpha | ('#' > x3::xdigit)) ];
}
int main () {
std::string input{ "/Foobar#F" }, attr;
auto iter = input.begin ();
if (phrase_parse (iter, input.end (), grammar::x, x3::space, attr)) {
std::cout << attr << std::endl;
}
}
Prints
/Foobar#F
Building with VS2013, specifying time_point::max() to a condition variable's wait_until results in an immediate timeout.
This seems unintuitive - I would naively expect time_point::max() to wait indefinitely (or at least a very long time). Can anyone confirm if this is documented, expected behaviour or something specific to MSVC?
Sample program below; note replacing time_point::max() with now + std::chrono::hours(1) gives the expected behaviour (wait_for exits once cv is notified, with no timeout)
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <future>
#include <functional>
void fire_cv( std::mutex *mx, std::condition_variable *cv )
{
std::unique_lock<std::mutex> lock(*mx);
printf("firing cv\n");
cv->notify_one();
}
int main(int argc, char *argv[])
{
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
std::condition_variable test_cv;
std::mutex test_mutex;
std::future<void> s;
{
std::unique_lock<std::mutex> lock(test_mutex);
s = std::async(std::launch::async, std::bind(fire_cv, &test_mutex, &test_cv));
printf("blocking on cv\n");
std::cv_status result = test_cv.wait_until( lock, std::chrono::steady_clock::time_point::max() );
//std::cv_status result = test_cv.wait_until( lock, now + std::chrono::hours(1) ); // <--- this works as expected!
printf("%s\n", (result==std::cv_status::timeout) ? "timeout" : "no timeout");
}
s.wait();
return 0;
}
I debugged MSCV 2015's implementation, and wait_until calls wait_for internally, which is implemented like this:
template<class _Rep,
class _Period>
_Cv_status wait_for(
unique_lock<mutex>& _Lck,
const chrono::duration<_Rep, _Period>& _Rel_time)
{ // wait for duration
_STDEXT threads::xtime _Tgt = _To_xtime(_Rel_time); // Bug!
return (wait_until(_Lck, &_Tgt));
}
The bug here is that _To_xtime overflows, which results in undefined behavior, and the result is a negative time_point:
template<class _Rep,
class _Period> inline
xtime _To_xtime(const chrono::duration<_Rep, _Period>& _Rel_time)
{ // convert duration to xtime
xtime _Xt;
if (_Rel_time <= chrono::duration<_Rep, _Period>::zero())
{ // negative or zero relative time, return zero
_Xt.sec = 0;
_Xt.nsec = 0;
}
else
{ // positive relative time, convert
chrono::nanoseconds _T0 =
chrono::system_clock::now().time_since_epoch();
_T0 += chrono::duration_cast<chrono::nanoseconds>(_Rel_time); //Overflow!
_Xt.sec = chrono::duration_cast<chrono::seconds>(_T0).count();
_T0 -= chrono::seconds(_Xt.sec);
_Xt.nsec = (long)_T0.count();
}
return (_Xt);
}
std::chrono::nanoseconds by default stores its value in a long long, and so after its definition, _T0 has a value of 1'471'618'263'082'939'000 (this changes obviously). Adding _Rel_time (9'223'244'955'544'505'510) results definitely in signed overflow.
We have already passed every negative time_point possible, so a timeout happens.
I'm trying to use c_escape_ch_p (see here) from boost::spirit to parse an escaped C++ string. But I'm getting a compiler error. Here is my code:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/home/classic/utility/escape_char.hpp>
#include <boost/spirit/home/classic/utility/confix.hpp>
#include <iostream>
#include <string>
namespace client {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
bool parse(Iterator first, Iterator last) {
using qi::char_;
qi::rule< Iterator, std::string(), ascii::space_type > text;
using namespace boost::spirit::classic;
qi::rule<Iterator, std::string()> myword2 =
confix_p('"', *c_escape_ch_p, '"') ; // ERROR!
text = myword2;
bool r = qi::phrase_parse(first, last, text, ascii::space);
if (first != last)
return false;
return r;
}
}
int main () {
std::string s = "\"foo\"";
bool ok = client::parse(s.begin(), s.end());
std::cout << "OK? " << (ok ? "y" : "n") << std::endl;
return 0;
}
The compiler error is a failed static assert instantiated from the line with confix:
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then the expression (expr) is not a valid spirit qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
So, it says it's not a valid expression. How is it used correctly?
P.S.: I'm using Boost 1.45.
You are trying to combine classic (old, V1, ...) boost::spirit::classic and (new, V2) boost::spirit::qi.
This is not going to work. The newer stuff is a complete, and incompatible, rewrite. See the 'Porting from Spirit 1.8.x' notes in the documentation.
As for the question on how to parse escaped C/C++ strings using boost::spirit::qi, the following article will be helpful:
Parsing Escaped String Input Using Spirit.Qi
I am working on a project where I need to change the behaviour of the XOpenDisplay function defined in X11/Xlib.h.
I have found an example, which should do exactly what I am looking for, but when I compile it, I get the following error messages:
XOpenDisplay_interpose.c:14: Error: conflicting types for »XOpenDisplay«
/usr/include/X11/Xlib.h:1507: Error: previous declaration of »XOpenDisplay« was here
Can anyone help me with that problem? What am I missing?
My program code so far - based on the example mentioned above:
#include <stdio.h>
#include <X11/Xlib.h>
#include <dlfcn.h>
Display *XOpenDisplay(char *display_name)
{
static Display *(*func)(char *);
Display *ret;
void* handle=NULL;
handle = dlopen ("XOpenDisplay_interpose.so", RTLD_LAZY);
if(!handle){
fprintf(stderr, "ERROR dlopen\n");
}
if(!func)
func = (Display *(*)(char *))dlsym(handle,"XOpenDisplay");
if(display_name)
printf("XOpenDisplay() is called with display_name=%s\n", display_name);
else
printf("XOpenDisplay() is called with display_name=NULL\n");
ret = func(display_name);
printf(" calling XOpenDisplay(NULL)\n");
ret = func(0);
printf("XOpenDisplay() returned %p\n", ret);
return(ret);
}
int XCloseDisplay(Display *display_name)
{
static int (*func)(Display *);
int ret;
void* handle=NULL;
handle = dlopen ("XOpenDisplay_interpose.so", RTLD_LAZY);
if(!handle){
fprintf(stderr, "ERROR dlopen\n");
}
if(!func)
func = (int (*)(Display *))dlsym(handle,"XCloseDisplay");
ret = (int)func(display_name);
printf("called XCloseDisplay(%p)\n", display_name);
return(ret);
}
int main()
{
}
Regards,
Andy.
The declaration reads like this:
Display *XOpenDisplay(_Xconst char *display_name)
So just adding a 'const' should suffice.