what is the difference between short signed int and signed int - c

I was referring a tutorial on c,I found that signed int & short signed int range are -32768 to 32767 and it's of 2 bytes, is their any difference, if not then why two kinds of declarations used.

It's platform specific - all that you can be sure of in this context is that sizeof(int) >= sizeof(short) >= 16 bits.

The best answer to your question can be found in the ANSI standard for C, section 2.2.4.2 - Numerical Limits. I reproduce the relevant parts of that section here for your convenience:
2.2.4.2 Numerical limits
A conforming implementation shall
document all the limits specified in
this section, which shall be specified
in the headers and
.
"Sizes of integral types "
The values given below shall be
replaced by constant expressions
suitable for use in #if preprocessing
directives. Their
implementation-defined values shall be
equal or greater in magnitude
(absolute value) to those shown, with
the same sign.
maximum number of bits for smallest
object that is not a bit-field (byte)
CHAR_BIT 8
minimum value for an object of type
signed char SCHAR_MIN
-127
maximum value for an object of type
signed char SCHAR_MAX
+127
maximum value for an object of type
unsigned char UCHAR_MAX
255
minimum value for an object of type
char CHAR_MIN see
below
maximum value for an object of type
char CHAR_MAX see
below
maximum number of bytes in a
multibyte character, for any supported
locale MB_LEN_MAX
1
minimum value for an object of type
short int SHRT_MIN
-32767
maximum value for an object of type
short int SHRT_MAX
+32767
maximum value for an object of type
unsigned short int USHRT_MAX
65535
minimum value for an object of type
int INT_MIN
-32767
maximum value for an object of type
int INT_MAX
+32767
maximum value for an object of type
unsigned int UINT_MAX
65535
minimum value for an object of type
long int LONG_MIN
-2147483647
maximum value for an object of type
long int LONG_MAX
+2147483647
maximum value for an object of type
unsigned long int ULONG_MAX
4294967295
The not so widely implemented C99 adds the following numeric types:
minimum value for an object of type long long int
LLONG_MIN -9223372036854775807 // -(263 - 1)
maximum value for an object of type long long int
LLONG_MAX +9223372036854775807 // 263 - 1
maximum value for an object of type unsigned long long int
ULLONG_MAX 18446744073709551615 // 264 - 1

A couple of other answers have correctly quoted the C standard, which places minimum ranges on the types. However, as you can see, those minimum ranges are identical for short int and int - so the question remains: Why are short int and int distinct? When should I choose one over the other?
The reason that int is provided is to provide a type that is intended to match the "most efficient" integer type on the hardware in question (that still meets the minimum required range). int is what you should use in C as your general purpose small integer type - it should be your default choice.
If you know that you'll need more range than -32767 to 32767, you should instead choose long int or long long int. If you are storing a large number of small integers, such that space efficiency is more important than calculation efficiency, then you can instead choose short (or even signed char, if you know that your values will fit into the -127 to 127 range).

C and C++ only make minimum size guarantees on their objects. There is no exact size guarantee that is made. You cannot rely on type short being exactly 2 bytes, only that it can hold values in the specified range (so it is at least two bytes). Type int is at least as large as short and is often larger. Note that signed int is a long-winded way to say int while signed short int is a long-winded way to say short int which is a long-winded way to say short. With the exception of type char (which some compilers will make unsigned), all the builtin integral types are signed by default. The types short int and long int are longer ways to say short and long, respectively.

A signed int is at least as large as a short signed int. On most modern hardware a short int is 2 bytes (as you saw), and a regular int is 4 bytes. Older architectures generally had a 2-byte int which may have been the cause of your confusion.
There is also a long int which is usually either 4 or 8 bytes, depending on the compiler.

Please read following expalination for signed char then we will talk about signed/unsigned int.
First I want to prepare background for your question.
................................................
char data type is of two types:
unsigned char;
signed char;
(i.e. INTEGRAL DATATYPES)
.................................................
Exaplained as per different books as:
char 1byte –128 to 127 (i.e. by default signed char)
signed char 1byte –128 to 127
unsigned char 1byte 0 to 255
.................................................
one more thing 1byte=8 bits.(zero to 7th bit)
As processor flag register reserves 7th bit for representing sign(i.e. 1=+ve & 0=-ve)
-37 will be represented as 1101 1011 (the most significant bit is 1),
+37 will be represented as 0010 0101 (the most significant bit is 0).
.................................................
similarly for char last bit is by default taken as signed
This is why?
Because char also depends on ASCII codes of perticular charectors(Eg.A=65).
In any case we are using char and using 7 bits only.
In this case to increase memory range for char/int by 1 bit we use unsigned char or unsigned int;
Thanks for the question.
similarly for 4bit int or 2bit int we need signed int & unsigned int

It depends on the platform.
Int is 32-bit wide on a 32-bit system and 64 bit wide on a 64-bit system(i am sure that this is ever the case).

I was referring a tutorial on c,I found that signed int & short signed int range are -32768 to 32767 and it's of 2 bytes.
That's a very old tutorial. The modern C standard is as per Paul R's answer. On a 32 bit architecture, normally:
short int is 16 bits
int is 32 bits
long int is 32 bits
long long int is 64 bits
the size of an int would normally only be 16 bits on a 16 bit machine. 16 bit machines are presumably limited to embedded devices these days.
On a 16 bit machine, sizes amay be like this:
short int is 16 bits
int is 16 bits
long int is 32 bits
long long int is 64 bits

Related

how can something be bigger than (unsigned long long) > LONG_MAX?

I found this code in an algorithm I need to update:
if (value > (unsigned long long) LONG_MAX)
EDIT: value is the result of a division of two uint64_t numbers.
I understand that (unsigned long long) LONG_MAX is a VERY big number:
#include "stdio.h"
#include "limits.h"
int main() {
unsigned long long ull = (unsigned long long) LONG_MAX;
printf("%lu",ull);
return 0;
}
prints 9223372036854775807
So what I am comparing here? In what case this if statement will evaluate to true?
A float or double can be larger than that. Appendix Ep5 of the C standard states that either type must be able to hold a value at least as large as 1E37 which is a larger value than LONG_MAX which must be at least 2147483647:
The values given in the following list shall be replaced by
implementation-defined constant expressions with values that are
greater than or equal to those shown:
#define DBL_MAX 1E+37
#define FLT_MAX 1E+37
#define LDBL_MAX 1E+37
So if value is either of those types, it could evaluate to true.
EDIT:
Since value is a uint64_t, whose max value is 18446744073709551615, this can also be larger than LONG_MAX.
how can something be bigger than (unsigned long long) > LONG_MAX?
Easily. LONG MAX is the maximum value that can be represented as a long int. Converting that to unsigned long long does not change its value, only its data type. The maximum value that can be represented as an unsigned long int is larger on every C implementation you're likely to meet. The maximum value of long long int is larger on some, and the maximum value of unsigned long long int is, again, larger on every C implementation you're likely to meet (much larger on some).
However, this ...
unsigned long long ull = (unsigned long long) LONG_MAX;
printf("%lu",ull);
... is not a conforming way to investigate the value in question because %lu is a formatting directive for type unsigned long, not unsigned long long. The printf call presented therefore has undefined behavior.
I found this code in an algorithm I need to update:
if (value > (unsigned long long) LONG_MAX)
EDIT: value is the result of a division of two uint64_t numbers.
[...]
In what case this if statement will
evaluate to true?
Supposing that value has type uint64_t, which is probably the same as unsigned long long in your implementation, the condition in that if statement will evaluate to true at least when the most-significant bit of value is set. If your long int is only 32 bits wide, however, then the condition will evaluate to true much more widely than that, because there are many 64-bit integers that are larger than the largest value representable as a signed 32-bit integer.
I would be inclined to guess that the code was indeed written under the assumption that long int is 32 bits wide, so that the if statement asks a very natural question: "can the result of the previous uint64_t division be represented as a long?" In fact, that's what the if statement is evaluating in any case, but it makes more sense if long is only 32 bits wide, which is typical of 32-bit computers and standard on both 32- and 64-bit Windows.
LONG_MAX is maximum value for a signed long. By standard it should be >= +2147483647 (fits in 32 bit signed)
There's also ULLONG_MAX for unsigned long long, which is currently most often 18446744073709551615. The standard mandates that to be >= than 9223372036854775807

What does (int)(unsigned char)(x) do in C?

In ctype.h, line 20, __ismask is defined as:
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
What does (int)(unsigned char)(x) do? I guess it casts x to unsigned char (to retrieve the first byte only regardless of x), but then why is it cast to an int at the end?
(unsigned char)(x) effectively computes an unsigned char with the value of x % (UCHAR_MAX + 1). This has the effect of giving a positive value (between 0 and UCHAR_MAX). With most implementations UCHAR_MAX has a value of 255 (although the standard permits an unsigned char to support a larger range, such implementations are uncommon).
Since the result of (unsigned char)(x) is guaranteed to be in the range supported by an int, the conversion to int will not change value.
Net effect is the least significant byte, with a positive value.
Some compilers give a warning when using a char (signed or not) type as an array index. The conversion to int shuts the compiler up.
The unsigned char-cast is to make sure the value is within the range 0..255, the resulting value is then used as an index in the _ctype array which is 255 bytes large, see ctype.h in Linux.
A cast to unsigned char safely extracts the least significant CHAR_BITs of x, due to the wraparound properties of an unsigned type. (A cast to char could be undefined if a char is a signed type on a platform: overflowing a signed type is undefined behaviour in c). CHAR_BIT is usually 8.
The cast to int then converts the unsigned char. The standard guarantees that an int can always hold any value that unsigned char can take.
A better alternative, if you wanted to extract the 8 least significant bits would be to apply & 0xFF and cast that result to an unsigned type.
I think char is implementation dependent, either signed or unsigned. So you need to be explicit by writing unsigned char, in order not to cast to a negative number. Then cast to int.

Can the type difference between constants 32768 and 0x8000 make a difference?

The Standard specifies that hexadecimal constants like 0x8000 (larger than fits in a signed integer) are unsigned (just like octal constants), whereas decimal constants like 32768 are signed long. (The exact types assume a 16-bit integer and a 32-bit long.) However, in regular C environments both will have the same representation, in binary 1000 0000 0000 0000.
Is a situation possible where this difference really produces a different outcome? In other words, is a situation possible where this difference matters at all?
Yes, it can matter. If your processor has a 16-bit int and a 32-bit long type, 32768 has the type long (since 32767 is the largest positive value fitting in a signed 16-bit int), whereas 0x8000 (since it is also considered for unsigned int) still fits in a 16-bit unsigned int.
Now consider the following program:
int main(int argc, char *argv[])
{
volatile long long_dec = ((long)~32768);
volatile long long_hex = ((long)~0x8000);
return 0;
}
When 32768 is considered long, the negation will invert 32 bits,
resulting in a representation 0xFFFF7FFF with type long; the cast is
superfluous.
When 0x8000 is considered unsigned int, the negation will invert
16 bits, resulting in a representation 0x7FFF with type unsigned int;
the cast will then zero-extend to a long value of 0x00007FFF.
Look at H&S5, section 2.7.1 page 24ff.
It is best to augment the constants with U, UL or L as appropriate.
On a 32 bit platform with 64 bit long, a and b in the following code will have different values:
int x = 2;
long a = x * 0x80000000; /* multiplication done in unsigned -> 0 */
long b = x * 2147483648; /* multiplication done in long -> 0x100000000 */
Another examine not yet given: compare (with greater-than or less-than operators) -1 to both 32768 and to 0x8000. Or, for that matter, try comparing each of them for equality with an 'int' variable equal to -32768.
Assuming int is 16 bits and long is 32 bits (which is actually fairly unusual these days; int is more commonly 32 bits):
printf("%ld\n", 32768); // prints "32768"
printf("%ld\n", 0x8000); // has undefined behavior
In most contexts, a numeric expression will be implicitly converted to an appropriate type determined by the context. (That's not always the type you want, though.) This doesn't apply to non-fixed arguments to variadic functions, such as any argument to one of the *printf() functions following the format string.
The difference would be if you were to try and add a value to the 16 bit int it would not be able to do so because it would exceed the bounds of the variable whereas if you were using a 32bit long you could add any number that is less than 2^16 to it.

Difference between signed / unsigned char [duplicate]

This question already has answers here:
What is an unsigned char?
(16 answers)
char!=(signed char), char!=(unsigned char)
(4 answers)
Closed 5 years ago.
So I know that the difference between a signed int and unsigned int is that a bit is used to signify if the number if positive or negative, but how does this apply to a char? How can a character be positive or negative?
There's no dedicated "character type" in C language. char is an integer type, same (in that regard) as int, short and other integer types. char just happens to be the smallest integer type. So, just like any other integer type, it can be signed or unsigned.
It is true that (as the name suggests) char is mostly intended to be used to represent characters. But characters in C are represented by their integer "codes", so there's nothing unusual in the fact that an integer type char is used to serve that purpose.
The only general difference between char and other integer types is that plain char is not synonymous with signed char, while with other integer types the signed modifier is optional/implied.
I slightly disagree with the above. The unsigned char simply means: Use the most significant bit instead of treating it as a bit flag for +/- sign when performing arithmetic operations.
It makes significance if you use char as a number for instance:
typedef char BYTE1;
typedef unsigned char BYTE2;
BYTE1 a;
BYTE2 b;
For variable a, only 7 bits are available and its range is (-127 to 127) = (+/-)2^7 -1.
For variable b all 8 bits are available and the range is 0 to 255 (2^8 -1).
If you use char as character, "unsigned" is completely ignored by the compiler just as comments are removed from your program.
There are three char types: (plain) char, signed char and unsigned char. Any char is usually an 8-bit integer* and in that sense, a signed and unsigned char have a useful meaning (generally equivalent to uint8_t and int8_t). When used as a character in the sense of text, use a char (also referred to as a plain char). This is typically a signed char but can be implemented either way by the compiler.
* Technically, a char can be any size as long as sizeof(char) is 1, but it is usually an 8-bit integer.
Representation is the same, the meaning is different. e.g, 0xFF, it both represented as "FF". When it is treated as "char", it is negative number -1; but it is 255 as unsigned. When it comes to bit shifting, it is a big difference since the sign bit is not shifted. e.g, if you shift 255 right 1 bit, it will get 127; shifting "-1" right will be no effect.
A signed char is a signed value which is typically smaller than, and is guaranteed not to be bigger than, a short. An unsigned char is an unsigned value which is typically smaller than, and is guaranteed not to be bigger than, a short. A type char without a signed or unsigned qualifier may behave as either a signed or unsigned char; this is usually implementation-defined, but there are a couple of cases where it is not:
If, in the target platform's character set, any of the characters required by standard C would map to a code higher than the maximum `signed char`, then `char` must be unsigned.
If `char` and `short` are the same size, then `char` must be signed.
Part of the reason there are two dialects of "C" (those where char is signed, and those where it is unsigned) is that there are some implementations where char must be unsigned, and others where it must be signed.
The same way -- e.g. if you have an 8-bit char, 7 bits can be used for magnitude and 1 for sign. So an unsigned char might range from 0 to 255, whilst a signed char might range from -128 to 127 (for example).
This because a char is stored at all effects as a 8-bit number. Speaking about a negative or positive char doesn't make sense if you consider it an ASCII code (which can be just signed*) but makes sense if you use that char to store a number, which could be in range 0-255 or in -128..127 according to the 2-complement representation.
*: it can be also unsigned, it actually depends on the implementation I think, in that case you will have access to extended ASCII charset provided by the encoding used
The same way how an int can be positive or negative. There is no difference. Actually on many platforms unqualified char is signed.

Conversion to short from char, odd results?

So my code has in it the following:
unsigned short num=0;
num=*(cra+3);
printf("> char %u\n",num);
cra is a char*
The problem is that it is getting odd output, sometimes outputting numbers such as 65501 (clearly not within the range of a char). Any ideas?
Thanks in advance!
Apparently *(cra+3) is a char of value '\xdd'. Since a char is signed, it actually means -35 (0xdd in 2's complement), i.e. 0x...fffffdd. Restricting this to 16-bit gives 0xffdd, i.e. 65501.
You need to make it an unsigned char so it gives a number in the range 0–255:
num = (unsigned char)cra[3];
Note:
1. the signedness of char is implementation defined, but usually (e.g. in OP's case) it is signed.
2. the ranges of signed char, unsigned char and unsigned short are implementation defined, but again commonly they are -128–127, 0–255 and 0–65535 respectively.
3. the conversion from signed char to unsigned char is actually -35 + 65536 = 65501.
char is allowed to be either signed or unsigned - apparently, on your platform, it is signed.
This means that it can hold values like -35. Such a value not within the range representable by unsigned short. When a number out of range is converted to an unsigned type, it is brought into range by repeatedly adding or subtracting one more than the maximum value representable in that type.
In this case, your unsigned short can represent values up to 65535, so -35 is brought into range by adding 65536, which gives 65501.
unsigned short has a range of (at least) 0 .. 65535 (link), the %u format specifier prints an unsigned int with a range of (commonly) 0 .. 4294967295. Thus, depending on the value of cra, the output appears to be completely sensible.
cra is just a pointer.
It hasn't been allocated any space, by way of malloc or calloc. So its contents are undefined . *(cra + 3) will evaluate to the contents of the location 3 bytes ahead of the location cra (assuming char occupies 1 byte). I believe that its contents are also undefined.
unsigned short takes up 2 bytes, atleast on my system. Hence it can hold values from 0 to 65536. So, your output is within its defined range

Resources