comparison operation [duplicate] - c

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unsigned and signed comparison
A riddle (in C)
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d = -1;
if (d < TOTAL_ELEMENTS)
printf("of course -1 is less than %d",TOTAL_ELEMENTS);
else
printf("how on earth");
return 0;
}
answer is:::Output of the above program is : how on earth

When you perform mixed signed vs. unsigned comparison (where signed type is not larger than unsigned one), the comparison is performed in unsigned domain, i.e. the signed operand is implicitly converted to unsigned type.
In your case TOTAL_ELEMENTS has type size_t, which is unsigned. That means that your d is also implicitly converted to size_t type. So, your d < TOTAL_ELEMENTS is actually interpreted as (size_t) d < TOTAL_ELEMENTS or (size_t) -1 < TOTAL_ELEMENTS.
(size_t) -1 is an extremely large positive value. It is actually the largest possible value of type size_t. Hence the result you get.
In your case you apparently want a signed comparison. For that you have to explicitly convert the unsigned value to signed type (paying close attention not to cause overflow). For example, this will work "as expected"
if (d < (int) TOTAL_ELEMENTS)
...

This is because sizeof_t is mapped to an unsigned long type, so -1 becomes 0xFFFFFFFFFFFFFFFF, a rather large positive integer. Try this:
#include<stdio.h>
#define TOTAL_ELEMENTS(a) ((int)(sizeof((a))/sizeof(*(a))))
int array[] = {23,34,12,17,204,99,16};
int main() {
int d = -1;
if (d < TOTAL_ELEMENTS(array)) {
printf("of course -1 is less than %d",TOTAL_ELEMENTS(array));
} else {
printf("how on earth");
}
return 0;
}
Note how I re-wrote your macro to reference array as its parameter, and added a cast to int to ensure that comparing to -1 would bring an expected result.

Related

Finding maximum value of a short int variable in C

I was working on Exercise 2-1 of K&R, the goal is to calculate the range of different variable types, bellow is my function to calculate the maximum value a short int can contain:
short int max_short(void) {
short int i = 1, j = 0, k = 0;
while (i > k) {
k = i;
if (((short int)2 * i) > (short int)0)
i *= 2;
else {
j = i;
while (i + j <= (short int)0)
j /= 2;
i += j;
}
}
return i;
}
My problem is that the returned value by this function is: -32768 which is obviously wrong since I'm expecting a positive value. I can't figure out where the problem is, I used the same function (with changes in the variables types) to calculate the maximum value an int can contain and it worked...
I though the problem could be caused by comparison inside the if and while statements, hence the typecasting but that didn't help...
Any ideas what is causing this ? Thanks in advance!
EDIT: Thanks to Antti Haapala for his explanations, the overflow to the sign bit results in undefined behavior NOT in negative values.
You can't use calculations like this to deduce the range of signed integers, because signed integer overflow has undefined behaviour, and narrowing conversion at best results in an implementation-defined value, or a signal being raised. The proper solution is to just use SHRT_MAX, INT_MAX ... of <limits.h>. Deducing the maximum value of signed integers via arithmetic is a trick question in standardized C language, and has been so ever since the first standard was published in 1989.
Note that the original edition of K&R predates the standardization of C by 11 years, and even the 2nd one - the "ANSI-C" version predates the finalized standard and differs from it somewhat - they were written for a language that wasn't almost, but not quite, entirely unlike the C language of this day.
You can do it easily for unsigned integers though:
unsigned int i = -1;
// i now holds the maximum value of `unsigned int`.
Per definition, you cannot calculate the maximum value of a type in C, by using variables of that very same type. It simply doesn't make any sense. The type will overflow when it goes "over the top". In case of signed integer overflow, the behavior is undefined, meaning you will get a major bug if you attempt it.
The correct way to do this is to simply check SHRT_MAX from limits.h.
An alternative, somewhat more questionable way would be to create the maximum of an unsigned short and then divide that by 2. We can create the maximum by taking the bitwise inversion of the value 0.
#include <stdio.h>
#include <limits.h>
int main()
{
printf("%hd\n", SHRT_MAX); // best way
unsigned short ushort_max = ~0u;
short short_max = ushort_max / 2;
printf("%hd\n", short_max);
return 0;
}
One note about your code:
Casts such as ((short int)2*i)>(short int)0 are completely superfluous. Most binary operators in C such as * and > implement something called "the usual arithmetic conversions", which is a way to implicitly convert and balance types of an expression. These implicit conversion rules will silently make both of the operands type int despite your casts.
You forgot to cast to short int during comparison
OK, here I assume that the computer would handle integer overflow behavior by changing into negative integers, as I believe that you have assumed in writing this program.
code that outputs 32767:
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
short int max_short(void)
{
short int i = 1, j = 0, k = 0;
while (i>k)
{
k = i;
if (((short int)(2 * i))>(short int)0)
i *= 2;
else
{
j = i;
while ((short int)(i + j) <= (short int)0)
j /= 2;
i += j;
}
}
return i;
}
int main() {
printf("%d", max_short());
while (1);
}
added 2 casts

warning: comparison of unsigned expression >= 0 is always true

I have the following error when compiling a C file:
t_memmove.c: In function ‘ft_memmove’:
ft_memmove.c:19: warning: comparison of unsigned expression >= 0 is always true
Here's the full code, via cat ft_memmove.c:
#include "libft.h"
#include <string.h>
void *ft_memmove(void *s1, const void *s2, size_t n)
{
char *s1c;
char *s2c;
size_t i;
if (!s1 || !s2 || !n)
{
return s1;
}
i = 0;
s1c = (char *) s1;
s2c = (char *) s2;
if (s1c > s2c)
{
while (n - i >= 0) // this triggers the error
{
s1c[n - i] = s2c[n - i];
++i;
}
}
else
{
while (i < n)
{
s1c[i] = s2c[i];
++i;
}
}
return s1;
}
I do understand that size_t is unsigned and that both integers will be >= 0 because of that. But since I'm subtracting one from the other, I don't get it. Why does this error come up?
If you subtract two unsigned integers in C, the result will be interpreted as unsigned. It doesn't automatically treat it as signed just because you subtracted. One way to fix that is use n >= i instead of n - i >= 0.
consider this loop:
for(unsigned int i=5;i>=0;i--)
{
}
This loop will be infinite because whenever i becomes -1 it'll be interprated as a very large possitive value as sign bit is absent in unsigned int.
This is the reason a warning is generated here
According to section 6.3.1.8 of the draft C99 standard Usual arithmetic conversions, since they are both of the same type, the result will also be size_t. The section states:
[...]Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result[...]
and later on says:
If both operands have the same type, then no further conversion is needed.
mathematically you can just move the i over to the other side of the expression like so:
n >= i
Arithmetic on unsigned results in an unsigned and that's why you are getting this warning. Better to change n - i >= 0 to n >= i.
Operations with unsigned operands are performed in the domain of unsigned type. Unsigned arithmetic follows the rules of modular arithmetic. This means that the result will never be negative, even if you are subtracting something from something. For example 1u - 5u does not produce -4. If produces UINT_MAX - 3, which is a huge positive value congruent to -4 modulo UINT_MAX + 1.

In C, sizeof operator returns 8 bytes when passing 2.5m but 4 bytes when passing 1.25m * 2

I do not understand why the sizeof operator is producing the following results:
sizeof( 2500000000 ) // => 8 (8 bytes).
... it returns 8, and when I do the following:
sizeof( 1250000000 * 2 ) // => 4 (4 bytes).
... it returns 4, rather than 8 (which is what I expected). Can someone clarify how sizeof determines the size of an expression (or data type) and why in my specific case this is occurring?
My best guess is that the sizeof operator is a compile-time operator.
Bounty Question: Is there a run time operator that can evaluate these expressions and produce my expected output (without casting)?
2500000000 doesn't fit in an int, so the compiler correctly interprets it as a long (or long long, or a type where it fits). 1250000000 does, and so does 2. The parameter to sizeof isn't evaluated, so the compiler can't possibly know that the multiplication doesn't fit in an int, and so returns the size of an int.
Also, even if the parameter was evaluated, you'd likely get an overflow (and undefined behavior), but probably still resulting in 4.
Here:
#include <iostream>
int main()
{
long long x = 1250000000 * 2;
std::cout << x;
}
can you guess the output? If you think it's 2500000000, you'd be wrong. The type of the expression 1250000000 * 2 is int, because the operands are int and int and multiplication isn't automagically promoted to a larger data type if it doesn't fit.
http://ideone.com/4Adf97
So here, gcc says it's -1794967296, but it's undefined behavior, so that could be any number. This number does fit into an int.
In addition, if you cast one of the operands to the expected type (much like you cast integers when dividing if you're looking for a non-integer result), you'll see this working:
#include <iostream>
int main()
{
long long x = (long long)1250000000 * 2;
std::cout << x;
}
yields the correct 2500000000.
[Edit: I did not notice, initially, that this was posted as both C and C++. I'm answering only with respect to C.]
Answering your followup question, "Is there anyway to determine the amount of memory allocated to an expression or variable at run time?": well, not exactly. The problem is that this is not a very well formed question.
"Expressions", in C-the-language (as opposed to some specific implementation), don't actually use any memory. (Specific implementations need some code and/or data memory to hold calculations, depending on how many results will fit into CPU registers and so on.) If an expression result is not stashed away in a variable, it simply vanishes (and the compiler can often omit the run-time code to calculate the never-saved result). The language doesn't give you a way to ask about something it doesn't assume exists, i.e., storage space for expressions.
Variables, on the other hand, do occupy storage (memory). The declaration for a variable tells the compiler how much storage to set aside. Except for C99's Variable Length Arrays, though, the storage required is determined purely at compile time, not at run time. This is why sizeof x is generally a constant-expression: the compiler can (and in fact must) determine the value of sizeof x at compile time.
C99's VLAs are a special exception to the rule:
void f(int n) {
char buf[n];
...
}
The storage required for buf is not (in general) something the compiler can find at compile time, so sizeof buf is not a compile-time constant. In this case, buf actually is allocated at run time and its size is only determined then. So sizeof buf is a runtime-computed expression.
For most cases, though, everything is sized up front, at compile time, and if an expression overflows at run-time, the behavior is undefined, implementation-defined, or well-defined depending on the type. Signed integer overflow, as in 2.5 billion multiplied by 2, when INT_MAX is just a little over 2.7 billion, results in "undefined behavior". Unsigned integers do modular arithmetic and thus allow you to calculate in GF(2k).
If you want to make sure some calculation cannot overflow, that's something you have to calculate yourself, at run time. This is a big part of what makes multiprecision libraries (like gmp) hard to write in C—it's usually a lot easier, as well as faster, to code big parts of that in assembly and take advantage of known properties of the CPU (like overflow flags, or double-wide result-register-pairs).
Luchian answered it already. Just for complete it..
C11 Standard states (C++ standard has similar lines) that the type of an integer literal with no suffix to designating the type is dertermined as follows:
From 6.4.4 Constants (C11 draft):
Semantics
4 The value of a decimal constant is computed base 10; that of an
octal constant, base 8; that of a hexadecimal constant, base 16. The
lexically first digit is the most significant.
5 The type of an integer constant is the first of the corresponding
list in which its value can be represented.
And the table is as follows:
Decimal Constant
int
int long int
long long int
Octal or Hexadecimal Constant
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
For Octal and Hexadecimal constants, even unsigned types are possible. So depending on your platform whichever in the above list (int or long int or long long int) fits first (in the order) will be the type of integer literal.
Another way to put the answer is to say that what is relevant to sizeof is not the value of the expression but it's type. sizeof returns the memory size for a type that can be provided either explicitely as a type or as an expression. In this case the compiler will compute this type at compile time without actually computing the expression (following known rules, for instance if you call a function, the resulting type is the type of the returned value).
As other poster stated there is an exception for variable length array (whose type size is only known at run time).
In other word you usually write things like sizeof(type) or sizeof expression where expression is an L-Value. Expression is almost never a complex computing (like the stupid example of calling a function above) : it would be useless anyway as it is not evaluated.
#include <stdio.h>
int main(){
struct Stype {
int a;
} svar;
printf("size=%d\n", sizeof(struct Stype));
printf("size=%d\n", sizeof svar);
printf("size=%d\n", sizeof svar.a);
printf("size=%d\n", sizeof(int));
}
Also notice that as sizeof is a language keyword, not a function parenthesis are not necessary before the trailing expression (we have the same kind of rule for return keyword).
For your follow-up question, there's no "operator", and there's no difference between the "compile time" size of an expression, and the "run time" size.
If you want to know if a given type can hold the result you're looking for, you can always try something like this:
#include <stdio.h>
#include <limits.h>
int main(void) {
int a = 1250000000;
int b = 2;
if ( (INT_MAX / (double) b) > a ) {
printf("int is big enough for %d * %d\n", a, b);
} else {
printf("int is not big enough for %d * %d\n", a, b);
}
if ( (LONG_MAX / (double) b) > a ) {
printf("long is big enough for %d * %d\n", a, b);
} else {
printf("long is not big enough for %d * %d\n", a, b);
}
return 0;
}
and a (slightly) more general solution, just for larks:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
/* 'gssim' is 'get size of signed integral multiplication */
size_t gssim(long long a, long long b);
int same_sign(long long a, long long b);
int main(void) {
printf("size required for 127 * 1 is %zu\n", gssim(127, 1));
printf("size required for 128 * 1 is %zu\n", gssim(128, 1));
printf("size required for 129 * 1 is %zu\n", gssim(129, 1));
printf("size required for 127 * -1 is %zu\n", gssim(127, -1));
printf("size required for 128 * -1 is %zu\n", gssim(128, -1));
printf("size required for 129 * -1 is %zu\n", gssim(129, -1));
printf("size required for 32766 * 1 is %zu\n", gssim(32766, 1));
printf("size required for 32767 * 1 is %zu\n", gssim(32767, 1));
printf("size required for 32768 * 1 is %zu\n", gssim(32768, 1));
printf("size required for -32767 * 1 is %zu\n", gssim(-32767, 1));
printf("size required for -32768 * 1 is %zu\n", gssim(-32768, 1));
printf("size required for -32769 * 1 is %zu\n", gssim(-32769, 1));
printf("size required for 1000000000 * 2 is %zu\n", gssim(1000000000, 2));
printf("size required for 1250000000 * 2 is %zu\n", gssim(1250000000, 2));
return 0;
}
size_t gssim(long long a, long long b) {
size_t ret_size;
if ( same_sign(a, b) ) {
if ( (CHAR_MAX / (long double) b) >= a ) {
ret_size = 1;
} else if ( (SHRT_MAX / (long double) b) >= a ) {
ret_size = sizeof(short);
} else if ( (INT_MAX / (long double) b) >= a ) {
ret_size = sizeof(int);
} else if ( (LONG_MAX / (long double) b) >= a ) {
ret_size = sizeof(long);
} else if ( (LLONG_MAX / (long double) b) >= a ) {
ret_size = sizeof(long long);
} else {
ret_size = 0;
}
} else {
if ( (SCHAR_MIN / (long double) llabs(b)) <= -llabs(a) ) {
ret_size = 1;
} else if ( (SHRT_MIN / (long double) llabs(b)) <= -llabs(a) ) {
ret_size = sizeof(short);
} else if ( (INT_MIN / (long double) llabs(b)) <= -llabs(a) ) {
ret_size = sizeof(int);
} else if ( (LONG_MIN / (long double) llabs(b)) <= -llabs(a) ) {
ret_size = sizeof(long);
} else if ( (LLONG_MIN / (long double) llabs(b)) <= -llabs(a) ) {
ret_size = sizeof(long long);
} else {
ret_size = 0;
}
}
return ret_size;
}
int same_sign(long long a, long long b) {
if ( (a >= 0 && b >= 0) || (a <= 0 && b <= 0) ) {
return 1;
} else {
return 0;
}
}
which, on my system, outputs:
size required for 127 * 1 is 1
size required for 128 * 1 is 2
size required for 129 * 1 is 2
size required for 127 * -1 is 1
size required for 128 * -1 is 1
size required for 129 * -1 is 2
size required for 32766 * 1 is 2
size required for 32767 * 1 is 2
size required for 32768 * 1 is 4
size required for -32767 * 1 is 2
size required for -32768 * 1 is 2
size required for -32769 * 1 is 4
size required for 1000000000 * 2 is 4
size required for 1250000000 * 2 is 8
Yes, sizeof() doesn't calculate the memory required for the result of that multiplication.
In the second case both literals : 1250000000 and 2 each requires 4 bytes of memory, hence sizeof() returns 4. If one of the values was above 4294967295 (2^32 - 1), you would have got 8.
But i don't know how sizeof() returned 8 for 2500000000. It returns 4 on my VS2012 compiler
The C11 Draft is here: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
You can find the Cx0 draft here: http://c0x.coding-guidelines.com/6.5.3.4.html
In both cases, section 6.5.3.4 is what you are looking for. Basically, your problem boils down to this:
// Example 1:
long long x = 2500000000;
int size = sizeof(x); // returns 8
// Example 2:
int x = 1250000000;
int y = 2;
int size = sizeof(x * y); // returns 4
In example 1, you have a long long (8 bytes), so it returns 8. In example 2, you have an int * int which returns an int, which is 4 bytes (so it returns 4).
To answer your bounty question: Yes and no. sizeof will not calculate the size needed for the operation you are trying to perform, but it will tell you the size of the results if you perform the operation with the proper labels:
long long x = 1250000000;
int y = 2;
int size = sizeof(x * y); // returns 8
// Alternatively
int size = sizeof(1250000000LL * 2); // returns 8
You have to tell it you are dealing with a large number or it will assume it is dealing with the smallest type it can (which in this case is int).
The most simple answer in one line is:
sizeof() is a function evaluated at COMPILE TIME who's input is a c type, the value of which is completely ignored
FURTHER DETAIL: ..therefore as 2500000000 is compiled it would have to be stored as a LONG as it is too long to fit in an int, therefore this argument is simply compiled as '(type) long'. However, 1250000000 and 2 both fit in type 'int' therefore that is the type passed to sizeof, since the resulting value is never stored as because the compiler simply is interested in the type, the multiplication is never evaluated.

automatic type conversions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
signed to unsigned conversions
A riddle (in C)
I am trying to understand why this program is not working
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
I came across this program when I was going through automatic type conversions in C.But I don't understand how conversions happen between signed and unsigned data types.Please explain.
Thank you,
Harish
sizeof() is of type unsigned, wile d is signed.
you check if d is smaller then an unsigned integer. Thus, the signed d is converted to unsinged.
But the bits representaion of the signed -1 when read as unsigned is greater then 2^31, and obviously greater then TOTAL_ELEMENTS-2, thus the condition is never met and you do not enter the for loop even once.
Look at this code snap, it might clear up things for you:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int x = 50;
int y = -1;
printf("x < y is actually %u < %u which yields %u\n", y,x,y < x);
return 0;
}
The above code prints:
x < y is actually 4294967295 < 50 which yields 0

A Macro using sizeof(arrays) is not giving the expected output

#include <stdio.h>
int arr[] = {1, 2,3,4,5};
#define TOT (sizeof(arr)/sizeof(arr[0]))
int main()
{
int d = -1, x = 0;
if(d<= TOT){
x = arr[4];
printf("%d", TOT);
}
printf("%d", TOT);
}
TOT has the value 5 but the if condition is failing..why is that?
Because there are "the usual arithmetic conversions" at work for the if.
The sizeof operator returns an unsigned type ... and d is converted to unsigned making it greater than the number of elements in arr.
Try
#define TOT (int)(sizeof(arr)/sizeof(arr[0]))
or
if(d<= (int)TOT){
That's because sizeof returns an unsigned number, while d is signed. When d implicitly converted to a singed number, and then it is much much larger than TOT.
You should get a warning about comparison of signed-unsigned comparison from the compiler.
Your expression for TOT is an unsigned value because the sizeof() operator always returns unsigned (positive) values.
When you compare the signed variable d with it, d gets automatically converted to a very large unsigned value, and hence becomes larger than TOT.
return type of sizeof is unsigned integer ....that is why if is failing ...because "d" which is treated as signed by the compiler is greater than TOT

Resources