My program will only run on Windows machines. I got multiple warnings, all the same. This is the warning:
Warning C4267 'argument': conversion from 'size_t' to 'int', possible loss of data
I get the warning when trying to send a string over a socket.
size_t ntohl_ch(char const* a)
{
size_t x; memcpy(&x, a, sizeof(x));
return ntohl(x);
}
size_t num = htonl(bufferSize); // bufferSize is also size_t
// Send buffer
size_t totalSent = 0;
size_t sent = 0;
while (totalSent < bufferSize)
{
sent = send(ClientSocket, buffer totalSent, bufferSize - totalSent, 0); // warning points to this line
if (sent == SOCKET_ERROR)
{
printf("error sending buffer %d\n", WSAGetLastError());
return SOCKET_ERROR;
}
totalSent = sent;
}
I know that send()
return int
and I can change sent
and totalSent
to int, but then inside send()
I try to do operation like plus or minus on int
and size_t
. Like this: int - size_t. I don't think that's the right way to do it.
The warning doesn't show when I cast all the size_t
parameters to int
inside send()
, but I think that's not the right way to do it because it can cause undefined behaviour. How can I solve this warning? Or can I just ignore it?
CodePudding user response:
That's not an important warning. Are you sure there isn't another one just below it which points out the actual bug?
No matter if using sys/socket.h or winsock2.h, the send
function returns -1 (SOCKET_ERROR
== -1) upon errors, as foretold in the Friendly Manual.
Therefore a correctly configured compiler such as gcc/mingw -Wall -Wextra
tells you about this severe bug here if (sent == SOCKET_ERROR)
:
warning: comparison of integer expressions of different signedness: 'size_t' {aka 'long long unsigned int'} and 'int' [-Wsign-compare]|
Since size_t
can never have the value -1
, this is a bug. Don't compare unsigned integers against negative values.
Instead of the bug, your compiler is apparently whining about some irrelevant stuff like passing size_t
instead of int
to the parameters.
From the Friendly Manual:
int WSAAPI send(
[in] SOCKET s,
[in] const char *buf,
[in] int len,
[in] int flags
);
So just use int
instead of size_t
as told in the manual and all your problems will go away.
CodePudding user response:
The warning doesn't show when I cast all the
size_t
parameters toint
insidesend()
, but I think that's not the right way to do it because it can cause undefined behaviour. How can I solve this warning? Or can I just ignore it?
There is only one parameter in the call to send()
that you need to cast: the third. For that parameter, you are passing the result of the subtraction of one size_t
from another, which will also be of size_t
type.
However, as pointed out in the comments, so long as the resulting difference is less than INT_MAX
(which seems likely, as that is 2147483647
on Windows), then you won't get any undefined behaviour from casting that result to an int
. So, just cast the result of that subtraction to silence the warning.
But note: (as also pointed out in the comments), you also have an issue with the return value from that call. The SOCKET_ERROR
constant is defined as (-1)
in the "WinSock2.h" header, so testing an (unsigned) size_t
value against that will, at best, confuse any future readers of your code1. It would be far better to have the sent
variable declared as an int
:
int sent = send(ClientSocket, buffer totalSent, (int)(bufferSize - totalSent), 0);
1 This "confusion" can arise from trying to remember what the "usual arithmetic conversion" rules are when having integral operands of different signedness for the =
and ==
operators. In your case, the size_t
has an rank greater than (64-bit build) or equal to (32-bit build) the int
'literal' (-1
), so (from the above-linked cppreference page):
If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
… further confusion could ensue, when trying to remember what the rule is for converting a negative integer to an unsigned type.