Understanding Sign extension - c

int main()
{
unsigned int b;
signed int a;
char z=-1;
b=z;
a=z;
printf("%d %d",a,b);
}
gives -1 -1. why does no sign extension occur, ALSO, when does it occur?

Sign extension DID occur, but you are printing the results incorrectly. In your printf you specified %d for b, but b is unsigned, you should have used %u to print b.
printf does not know the type of its arguments and uses the format specifies to interpret them.
printf("%d %u",a,b);

Because printf looks at the raw memory, not the type. use %u to print the value as unsigned.
See.
http://ideone.com/Qpcbg

Related

Problems with the read syscall [duplicate]

pixel_data is a vector of char.
When I do printf(" 0x%1x ", pixel_data[0] ) I'm expecting to see 0xf5.
But I get 0xfffffff5 as though I was printing out a 4 byte integer instead of 1 byte.
Why is this? I have given printf a char to print out - it's only 1 byte, so why is printf printing 4?
NB. the printf implementation is wrapped up inside a third party API but just wondering if this is a feature of standard printf?
You're probably getting a benign form of undefined behaviour because the %x modifier expects an unsigned int parameter and a char will usually be promoted to an int when passed to a varargs function.
You should explicitly cast the char to an unsigned int to get predictable results:
printf(" 0x%1x ", (unsigned)pixel_data[0] );
Note that a field width of one is not very useful. It merely specifies the minimum number of digits to display and at least one digit will be needed in any case.
If char on your platform is signed then this conversion will convert negative char values to large unsigned int values (e.g. fffffff5). If you want to treat byte values as unsigned values and just zero extend when converting to unsigned int you should use unsigned char for pixel_data, or cast via unsigned char or use a masking operation after promotion.
e.g.
printf(" 0x%x ", (unsigned)(unsigned char)pixel_data[0] );
or
printf(" 0x%x ", (unsigned)pixel_data[0] & 0xffU );
Better use the standard-format-flags
printf(" %#1x ", pixel_data[0] );
then your compiler puts the hex-prefix for you.
Use %hhx
printf("%#04hhx ", foo);
Then length modifier is the minimum length.
Width-specifier in printf is actually min-width. You can do printf(" 0x%2x ", pixel_data[0] & 0xff) to print lowes byte (notice 2, to actually print two characters if pixel_data[0] is eg 0xffffff02).

Printf in C (types)

I just started programming in C. And I don't really understand the following code:
printf("%zu",i);
or instead of %zu what are the other things that I can write (I know that they depend on the type of i) and which one is for what?
It's a format modifier for siz_t and size_t is unsigned.
printf("%zu\n", x); // print unsigned decimal
printf("%zx\n", x); // print hexadecimal
printf("%zd\n", y); // print signed decimal
It takes unsigned size_t i and prints it to the stdout.

Printing int type with %lu - C+XINU

I have a given code, in my opinion there is something wrong with that code:
I compile under XINU.
The next variables are relevant :
unsigned long ularray[];
int num;
char str[100];
There is a function returns int:
int func(int i)
{
return ularray[i];
}
now the code is like this:
num = func(i);
sprintf(str, "number = %lu\n", num);
printf(str);
The problem is I get big numbers while printing with %lu, which is not correct.
If i change the %lu to %d, i get the correct number.
For example: with %lu i get 27654342, while with %d i get 26, the latter is correct;
The variables are given, the declaration of the function is given, i write the body but it must return int;
My questions are:
I'm not familiar with 'sprintf' maybe the problem is there?
I assigned unsigned long to int and then print the int with %lu, is That correct?
How can i fix the problem?
Thanks in advance.
Thanks everyone for answering.
I just want to mention I'm working under XINU, well i changed the order of the compilation of the files and what you know... its working and showing same numbers on %lu and %d.
I'm well aware that assigning 'unsigned long' to int and then printing with %lu is incorrect coding and may result loss of data.
But as i said, the code is given, i couldn't change the variables and the printing command.
I had no errors or warnings btw.
I have no idea why changing the compilation order fixed the problem, if someone have an idea you are more then welcome to share.
I want to thank all of you who tried to help me.
I assigned unsigned long to int and then print the int with %lu, is That correct?
No, it isn't correct at all. Think about it a bit! Printf tries to access the memory represented by the variables you pass in and in your case, unsigned long is represented on more bits than int, hence when printf is told to print an unsigned int, it'll read past your actual int and read some other memory which is probably garbage, hence the random numbers. If printf had a prototype mentioning an unsigned long exactly, the compiler could perform an implicit cast and fill the rest of the unwanted memory with zeroes, but since it's not the case, you have to do either one of these solutions:
One, explicit cast your variable:
printf("%lu", (unsigned long)i);
Two, use the correct format specifier:
printf("%d", i);
Also, there are problems with assigning an unsigned long to an int - if the long contains a too big number, then it won't fit into the int and get truncated.
1) the misunderstanding is format specifiers in general
2) num is an int -- therefore, %d is correct when an int is what you want to print.
3) ideally
int func(int i) would be unsigned long func(size_t i)
and int num would be unsigned long num
and sprintf(str, "number = %d\n", num); would be sprintf(str, "number = %lu\n", num);
that way, there would be no narrowing and no conversions -- the type/values would be correctly preserved throughout execution.
and to be pedantic, printf should be printf("%s", str);
if you turn your warning levels way up, your compiler will warn you of some of these things. i have been programming for a long time, and i still leave the warning level obnoxiously high (by some people's standards).
If you have an int, use %d (or %u for unsigned int). If you have a long, use %ld (or %lu for unsigned long).
If you tell printf that you're giving it a long but only pass an int, you'll print random garbage. (Technically that would be undefined behavior.)
It doesn't matter if that int somehow "came from" a long. Once you've assigned it to something shorter, the extra bytes are lost. You only have a int left.
I assigned unsigned long to int and then print the int with %lu, is That correct?
No, and I suggest not casting to int first or else simply using int as the array type. It seems senseless to store a much larger representation and only use a smaller one. Either way, the sprint results will always be off until you properly pair the type (technically the encoding) of the variable with the format's conversion specifier. This means that if you pass an unsigned long, use %ul, if it's an int, use either %i or %d (the difference is that %d is always base-10, %i can take additional specifiers to print in other bases.
How can I fix the problem?
Change the return of your func and the encoding of num to unsigned long
unsigned long ularray[];
unsigned long num;
char str[100];
unsigned long func(int i)
{
return ularray[i];
}

Convert int to double

I ran this simple program, but when I convert from int to double, the result is zero. The sqrt of the zeros then displays negative values. This is an example from an online tutorial so I'm not sure why this is happening. I tried in Windows and Unix.
/* Hello World program */
#include<stdio.h>
#include<math.h>
main()
{ int i;
printf("\t Number \t\t Square Root of Number\n\n");
for (i=0; i<=360; ++i)
printf("\t %d \t\t\t %d \n",i, sqrt((double) i));
}
Maybe this?
int number;
double dblNumber = (double)number;
The problem is incorrect use of printf format - use %g/%f instead of %d
BTW - if you are wondering what your code did here is some abridged explanation that may help you in understanding:
printf routine has treated your floating point result of sqrt as integer. Signed, unsigned integers have their underlying bit representations (put simply - it's the way how they are 'encoded' in memory, registers etc). By specifying format to printf you tell it how it should decipher that bit pattern in specific memory area/register (depends on calling conventions etc). For example:
unsigned int myInt = 0xFFFFFFFF;
printf( "as signed=[%i] as unsigned=[%u]\n", myInt, myInt );
gives: "as signed=[-1] as unsigned=[4294967295]"
One bit pattern used but treated as signed first and unsigned later. Same applies to your code. You've told printf to treat bit pattern that was used to 'encode' floating point result of sqrt as integer. See this:
float myFloat = 8.0;
printf( "%08X\n", *((unsigned int*)&myFloat) );
prints: "41000000"
According to single precision floating point encoding format.
8.0 is simply (-1)^0*(1+fraction=0)*2^(exp=130-127)=2*3=8.0 but printed as int looks like just 41000000 (hex of course).
sqrt() return a value of type double. You cannot print such a value with the conversion specifier "%d".
Try one of these two alternatives
printf("\t %d \t\t\t %f \n",i, sqrt(i)); /* use "%f" */
printf("\t %d \t\t\t %d \n",i, (int)sqrt(i)); /* cast to int */
The i argument to sqrt() is converted to double implicitly, as long as there is a prototype in scope. Since you included the proper header, there is no need for an explicit conversion.

greater integer width

i m trying to enter a five digit number greater than 32767 and i used "unsigned" while declaring int number, and when i m trying to print the same number it prints some arbitary negative number,
results get overflowed......
pls help me out
Without seeing your code, I am guessing you are using %d or %i in the printf statement. Use %u instead.
Print unsigned values using "%u" instead of "%d".
Until you show some of the code, I can't be sure of anything.
But AFAIK you shouldn't be able to print out a negative number if you're printing out an uint – even if it overflows, the integer will always hold a positive number, as far as C is concerned.
So there's something else wrong.
Use correct format specifier.
%d for int
%u for unsigned int.
Using incorrect format specifier in printf() may cause Undefined Behavior.
For example, the following code invokes Undefined Behavior(UB).
#include<stdio.h>
int main(void)
{
unsigned int z=Some_value; /*Some_value is an unsigned int */
printf("%d",z);
/*UB as format specifier for unsigned int is incorrect,it should be %u not %d*/
}
I guess int is 16bit on your machine/compiler.
Though I don't know what your platform is, I guess that long would solve your problem (it is 32bit or more on all platforms I know). Print it with %ld instead of %d.
Don't get tempted to use unsigned and %u, because they will just give you numbers up to 65536, and I guess that you want more.

Resources