strange warning

A

asdf

I got a warning from the following statement:

fprintf(point_file, "CONTOUR\nCLOSE\n%d\n", curve.size());

warning: format '%d' expects type 'int', but argument 3 has type
'size_t'

should I change the coding to

fprintf(point_file, "CONTOUR\nCLOSE\n%u\n", curve.size());

?

Thanks all.
 
V

Victor Bazarov

asdf said:
I got a warning from the following statement:

fprintf(point_file, "CONTOUR\nCLOSE\n%d\n", curve.size());

warning: format '%d' expects type 'int', but argument 3 has type
'size_t'

should I change the coding to

fprintf(point_file, "CONTOUR\nCLOSE\n%u\n", curve.size());

?

It could be that you need %Lu if sizeof(size_t) > sizeof(int) on
your system. Also, see the documentation for your compiler about
what format string to use to print out 'size_t'.

V
 
A

Andrey Tarasevich

asdf said:
I got a warning from the following statement:

fprintf(point_file, "CONTOUR\nCLOSE\n%d\n", curve.size());

warning: format '%d' expects type 'int', but argument 3 has type
'size_t'

should I change the coding to

fprintf(point_file, "CONTOUR\nCLOSE\n%u\n", curve.size());

?
...

You should explicitly cast the return value of 'curve.size()' to some built-in
integral type that is sufficiently large to hold the value, and then use the
format specifier for that type. For example

fprintf(point_file, "CONTOUR\nCLOSE\n%lu\n", (unsigned long) curve.size());

Your platform might also provide an implementation-specific format specifier for
printing 'size_t'. So you might decide to use that instead (assuming that return
type of 'size_t' is a part of the interface specification of that 'size()' method).
 
I

Ian Collins

Andrey said:
You should explicitly cast the return value of 'curve.size()' to some built-in
integral type that is sufficiently large to hold the value, and then use the
format specifier for that type. For example

fprintf(point_file, "CONTOUR\nCLOSE\n%lu\n", (unsigned long) curve.size());
Isn't that rather dangerous? If the return type of curve.size() were to
change, the cast would mask the warning.

Better to find and use the correct format specifier and count your self
lucky your compiler is kind enough to issue that diagnostic.
 
O

Old Wolf

Ian said:
Isn't that rather dangerous? If the return type of curve.size() were to
change, the cast would mask the warning.

Better to find and use the correct format specifier and count your self
lucky your compiler is kind enough to issue that diagnostic.

Note that there is no correct specifier for 'size_t' in C++
(C99 does have one).

If you are suggesting to not cast curve.size() but use a
specifier such as %lu, then what happens if you port to
a system where size_t is different? Silent undefined behaviour.

IMHO it is best to have an implementation-defined result
or a compile error, as Andrey's case will give if size() is
changed to return something else, instead of undefined
behaviour.
 
J

Jerry Coffin

[ ... ]
Note that there is no correct specifier for 'size_t' in C++
(C99 does have one).

TR1 for the C++ library includes all of inttypes.h, stdint.h, etc.

Since we're using C++, why not use an iostream that already knows how
to deal with size_t?
 
O

Old Wolf

Jerry said:
Since we're using C++, why not use an iostream that already knows how
to deal with size_t?

The OP has to write to a FILE* .

He could write the size_t with a stringstream and then write
the string to the FILE*, I suppose.
 
J

Jim Langston

asdf said:
I got a warning from the following statement:

fprintf(point_file, "CONTOUR\nCLOSE\n%d\n", curve.size());

warning: format '%d' expects type 'int', but argument 3 has type
'size_t'

should I change the coding to

fprintf(point_file, "CONTOUR\nCLOSE\n%u\n", curve.size());

?

Thanks all.

You are most likely using a microsoft compiler. Although size_t is
currently defined as an unsigned int, when you move to a 64 bit compiler it
would change it's size (most likely unsigned long long int or such).

Just about anywhere you use size_t you'll get a warning unless you are
assigning a size_t var to a size_t var.

In your particular case, there is one way to make it safer, although you'll
still get a warning.

std::stringstream ConvStream;
ConvStream << "CONTOUR\nCLOSE\n" << curve.size() << "\n";
fprintf(point_file, ConvStream.str());

The reason this is safer is that when you do switch to a 64 bit compiler
this code will still work without any changes. Your existing code would
have to change the %d to %ld or something, and size_t is unsigned anyway.

Personally, I got tired of _64 bit warnings and disabled them in my compiler
with a project setting.
 
O

Old Wolf

Jim said:
In your particular case, there is one way to make it safer, although you'll
still get a warning.

std::stringstream ConvStream;
ConvStream << "CONTOUR\nCLOSE\n" << curve.size() << "\n";

There would be no warning for that code
fprintf(point_file, ConvStream.str());

fprintf(point_file, ConvStream.str().c_str());

or in fact I would prefer

fprintf(point_file, "%s", ConvStream.str().c_str());
Personally, I got tired of _64 bit warnings and disabled them in my compiler
with a project setting.

Worry about it when the time comes, eh?
 
J

Jim Langston

Old Wolf said:
There would be no warning for that code

It gave me a warning in MS VC++ .net 2003
fprintf(point_file, ConvStream.str().c_str());

or in fact I would prefer

fprintf(point_file, "%s", ConvStream.str().c_str());


Worry about it when the time comes, eh?

Well, I was looking at all the warnings, the warnings I was getting was
about storing a SOCKET in an unsigned int which was being used for an ID in
client server. If and when I went to a 64 bit system I would turn warnings
back on, and just change the ID to unsigned long int or whatever it is they
then required for a 64 bit int. Absolutely nothing I can do about it now,
so what good are the warnings?
 
J

Jim Langston

Old Wolf said:
What is the warning?

size_t Value = 10;

std::stringstream Stream;
Stream << Value;

c:\Source\working\console\console.cpp(11) : warning C4267: 'argument' :
conversion from 'size_t' to 'unsigned int', possible loss of data
 
O

Old Wolf

Jim said:
size_t Value = 10;

std::stringstream Stream;
Stream << Value;

c:\Source\working\console\console.cpp(11) : warning C4267: 'argument' :
conversion from 'size_t' to 'unsigned int', possible loss of data

Ok. I thought there was a version of std::eek:stream::eek:perator<<
taking a size_t, but in fact there isn't.

I'm not sure what you would do with a size_t that's bigger than
an unsigned long (or if that is even possible).
 
J

Jim Langston

Old Wolf said:
Ok. I thought there was a version of std::eek:stream::eek:perator<<
taking a size_t, but in fact there isn't.

I'm not sure what you would do with a size_t that's bigger than
an unsigned long (or if that is even possible).

Well, that's the thing. If this code was switched to a 64 bit system, it
would still work as expected, since at that time they would add a 64 bit
unsigned int to ostream.

The problem comes in when you attempt to store the value in some way, such
as into an unsigned int, that when you switch to a 64 bit compiler it will
break unless you change the unsigned int to a 64 bit int. Using
stringstream, however, it's being converted but not stored.
 
P

peter koch

Old said:
Ok. I thought there was a version of std::eek:stream::eek:perator<<
taking a size_t, but in fact there isn't.

There surely is - look at my other reply.

/Peter
 
P

peter koch

Jim said:
size_t Value = 10;

std::stringstream Stream;
Stream << Value;

c:\Source\working\console\console.cpp(11) : warning C4267: 'argument' :
conversion from 'size_t' to 'unsigned int', possible loss of data

This is just a warning from the Microsoft Compiler - and only one that
warns about a portability problem (when porting to 64-bit code).
Furthermore, these warnings are quite unreliable and should not
normally be on. As Microsofts own documentation states:

In this situation, C4267 is caused by a limitation in /Wp64 warnings.
On x86, std::cout<<range_index resolves to the overload of operator<<
that accepts an unsigned int, since size_t is an unsigned int on Win32.
C4267 occurs because you passed a size_t as an unsigned int argument,
which would cause truncation on Win64 where size_t is 64-bit, but
unsigned int is still 32-bit. This can be ignored because if you
compiled for Win64, std::cout<<range_index would resolve to the
overload of operator<< that accepts an unsigned __int64, since that's
what type size_t is on Win64. The 32-bit compiler doesn't notice, so it
warns.

/Peter
 
O

Old Wolf

peter said:
There surely is - look at my other reply.

According to the 1998 version of the standard, the only overloads
for operator<< are: charT, char, signed char, unsigned char,
complex<T>, bool, short, unsigned short, int, unsigned int,
long, unsigned long, float, double, long double, and some pointers.

The standard doesn't appear to say anything about the type
of size_t; in fact, as far as I can see, it doesn't even say that
it has to be an integral type.

17.4.4.7 says:
Unless explicitly stated otherwise, types with distinct names are
distinct types.174)

and the footnote is:
174) An implicit exception to this rule are types described as
synonyms for basic integral types, such as size_t (18.1) and
streamoff (27.4.1).

Although 27.4.1 defines streamoff as being a synonym for an
integral type, 18.1 (or any other section for that matter)
does not describe size_t as being a synonym for anything.
 
K

Kai-Uwe Bux

Old said:
According to the 1998 version of the standard, the only overloads
for operator<< are: charT, char, signed char, unsigned char,
complex<T>, bool, short, unsigned short, int, unsigned int,
long, unsigned long, float, double, long double, and some pointers.

The standard doesn't appear to say anything about the type
of size_t; in fact, as far as I can see, it doesn't even say that
it has to be an integral type.

17.4.4.7 says:
Unless explicitly stated otherwise, types with distinct names are
distinct types.174)

and the footnote is:
174) An implicit exception to this rule are types described as
synonyms for basic integral types, such as size_t (18.1) and
streamoff (27.4.1).

Although 27.4.1 defines streamoff as being a synonym for an
integral type, 18.1 (or any other section for that matter)
does not describe size_t as being a synonym for anything.

The C++ standard says that std::size_t is defined in <cstddef>. Also [18/3]
says that <cstddef> provides the same contents as the C header stddef.h.
Thus, the C++ standard refers to the C standard here. I have no copy of the
C standard, but the draft version provides in [7.17] that size_t is "the
unsigned integer type of the result of the sizeof operator".


Best

Kai-Uwe Bux
 
J

Jerry Coffin

[ ... ]
The standard doesn't appear to say anything about the type
of size_t; in fact, as far as I can see, it doesn't even say that
it has to be an integral type.

size_t is defined in cstddef/stddef.h. Section 18.1/3 describes
cstddef as: "The contents are the same as the Standard C library
header <stddef.h> with the following changes:" (and none of the
changes applies to size_t, only to offsetof and NULL).

In the C90 standard, section 7.1.6 says size_t is "the unsigned
integral type of the result of the sizeof operator;"

So, size_t must be a synonym for one of the unsigned integral types
(unsigned char, unsigned short, unsigned int, unsigned long or
possibly "plain" char, if it happens to be unsigned). In C99 and
almost certainly the next version of C++, unsigned long long will be
possible as well, but that type doesn't exist in C++ as it's
currently defined (though many compilers support it anyway).
 
O

Old Wolf

Jerry said:
(e-mail address removed) says...

size_t is defined in cstddef/stddef.h. Section 18.1/3 describes
cstddef as: "The contents are the same as the Standard C library
header <stddef.h> with the following changes:" (and none of the
changes applies to size_t, only to offsetof and NULL).

In the C90 standard, section 7.1.6 says size_t is "the unsigned
integral type of the result of the sizeof operator;"

So, size_t must be a synonym for one of the unsigned integral types
(unsigned char, unsigned short, unsigned int, unsigned long or
possibly "plain" char, if it happens to be unsigned). In C99 and
almost certainly the next version of C++, unsigned long long will be
possible as well, but that type doesn't exist in C++ as it's
currently defined (though many compilers support it anyway).

In C99, size_t does not have to be a synonym for an
integral type (although it does in C90, as you point out).

Another can of worms for the C++ standards committee :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top