How to assign an int to unsigned long using C? - c

I am using C language. There is a function named "npu_session_total".
Then, I will use the return value of this func and assign it to an unsigned long variable "accelerated_count".
int npu_session_total(void)
{
// this will return an int
return atomic_read(&npu_session_count);
}
........
unsigned long accelerated_count = npu_session_total();
Will this cause any problems? How can I do the cast?
Thanks!

Assigning an int to a unsigned long can be done simply as OP did. It is well defined in C. When some_int_value >= 0 it will always fit unchanged into an unsigned long.
INT_MAX <= UINT_MAX <= ULONG_MAX
No cast, masking, nor math is needed - just like OP did.
unsigned long some_unsigned_long_object = some_int_value;
The trick is when some_int_value < 0. The value saved will be some_int_value + ULONG_MAX + 1. #AnT Now is this OK for OP's code? Perhaps not.
A safer conversion would test for negativeness first.
int session_total = npu_session_total();
if (session_total < 0) {
Handle_Negative_Case(session_total);
}
else {
unsigned long accelerated_count = npu_session_total();
...
}
#OP comments that the int value should never be negative. Defensive coding would still detect negative values and handle that. Maybe a simple error message and exit.

Related

what is behavior when char is compared with unsigned short in c language?

When I run the following program:
void func(unsigned short maxNum, unsigned short di)
{
if (di == 0) {
return;
}
char i;
for (i = di; i <= maxNum; i += di) {
printf("%u ", i);
}
printf("\n");
}
int main(int argc, char **argv)
{
func(256, 100);
return 0;
}
It is endless loop, but i wonder when char is compared with unsigned short, is char translated to unsigned short? In this situation, char is overflow and larger than maxNum. I really do not know how to explain the results of this program.
Implementation defined behavior, Undefined behavior and CHAR_MAX < 256
Let us sort out:
... unsigned short maxNum
... unsigned short di
char i;
for (i = di; i <= maxNum; i += di) {
printf("%u ", i);
}
char may be a signed char or an unsigned char. Let us assume it is signed.
unsigned short may have the same range as unsigned when both are 16-bit. Yet it is more common to find unsigned short as 16-bit and int, unsigned as 32-bit.
Other possibles exist, yet let us go forward with the above two assumptions.
i = di could be interesting if the value assigned was outside the range of a char, but 100 is always within char range, so i is 100.
Each argument in i <= maxNum goes through usual integer promotions so the signed char i first becomes an int 100 and the 16-bit maxNum becomes an int 256. As 100 < 256 is true, the loop body is entered. Notice i would never expect to have a value as large as 256 since CHAR_MAX is less than 256 - even on following loops - This explains the seen forever loop. But wait there's more
With printf("%u ", i);, printf() expects a matching unsigned argument. But i as a type with less range then int gets promoted to a int with the same value as part of a ... argument. Usually printing mis-matched specifiers and type is undefined behavior with an exception: when the value is representable as both a signed and unsigned type. As 100 is the first time, all is OK.
At the loop end, i += di is like i = i + di;. The addition arguments go through usual integer promotions and become int 100 added to int 100. That sum is 200. So far nothing strange. Yet assigning a 200 to a signed char coverts the 200 as it is out of range. This is implementation defined behavior. The assigned value could have been 0 or 1 or 2.... Typically, the value is wrapped around ("modded") by adding/subtracting 256 until in range. 100 + 100 -256 --> -56.
But the 2nd printf("%u ", i); attempts printing -56 and that is undefined behavior.
Tip: enable all warnings, Good compilers will point out many of these problems and save you time.
I got the answer from http://www.idryman.org/blog/2012/11/21/integer-promotion/ , both char and unsigned short are translated to int which can explain the process and result of this programs.

converting from signed int to unsigned int without casting

int isNegative(int x) {
return ((unsigned) x)>> 31;
}
I'm writing a function that takes 32 bits and returns 1 if x<0, and 0 otherwise. How do I convert a signed int to an unsigned int without casting.
OP has different implied questions
a function that takes 32 bits and returns 1 if x<0, and 0 otherwise.
int isNegative(int x) {
return x < 0;
}
// or maybe return bool/_Bool
bool isNegative(int x) {
return x < 0;
}
// or pedantically
int isNegative(int_least32_t x) {
return x < 0;
}
// or pedantically and nearly universally portable,
int isNegative(int32_t x) {
return x < 0;
}
converting from signed int to unsigned int without casting (and)
How do I convert a signed int to an unsigned int without casting.
Simply assign the value
int i;
unsigned u = i;
Attempting to use >> to combined these two risk implementation defined behavior and should be avoided unless compelling reasons are given.
EXAMPLE An example of implementation-defined behavior is the propagation of the high-order bit when a signed integer is shifted right. C11ยง3.4.2 2
In this case you don't need to. If you get rid of the cast, right shifting retains the sign bit.
Assuming int is 32 bit, removing the cast results in -1 for negative numbers and 0 for nonnegative numbers. While the actual return value differs for the nonnegative case, in a Boolean context it will work as you expect.
Your question is to write a function that takes 32 bits and returns 1 if x < 0
int isNegative(int x) {
return x < 0;
}
This will work no matter what the size of int and does not invoke any type conversions. I suppose you have over-thought this problem.
There is a variety of operations that perform automatic type conversions, among them assignments, arithmetic operations under certain conditions, and function calls (conversion of certain argument values).
Thus, you could achieve conversion of (signed) int arguments to unsigned int simply by declaring that to be the parameter type:
int isNegative(unsigned x) {
return x >> 31;
}
Admittedly, however, that function interface could be a little confusing. You might therefore prefer to do this:
int isNegative(int x) {
unsigned ux = x;
return x >> 31;
}
However, I don't think either of those is as clear as your original version, with its cast. Type conversion is the entire purpose of a cast, and when conversion is what you need (and all that you need), a cast is the right tool for the job.
Of course, I do overall prefer the even simpler family of approaches suggested by #chux.

How do I mute this error : "integer literal is too large to be represented in a signed integer type"

I have this school assignment in C where I will be corrected with the following flags :
-Wall -Wextra -Werror
So this harmless warning becomes an error and prevents compilation :
integer literal is too large to be represented in a signed integer type
(code still works) but if I can't mute it my work will be considered wrong
Here is my code :
static unsigned long long piece_to_map(unsigned short little)
{
static unsigned short row;
unsigned long long big;
char i;
unsigned long long mask_left;
unsigned long long mask_top;
mask_left = 9259542123273814144;
mask_top = 18374686479671623680;
row = 15;
big = 0;
i = 0;
while (i < 16)
{
big |= (little & (row << i)) << i;
i += 4;
}
while ((big & mask_t) == 0)
big = big << 8;
while ((big & mask_l) == 0)
big = big << 1;
return (big);
}
What I'm trying to achieve here is to transform an unsigned short (representing a shape in a 4x4 square) to an unsigned long long representing the same shape in a 8x8 square having the shape cornered top-left. It works perfectly and according to my expectations, I just need to avoid having the warning. I was formerly using the (normally equivalent) binary expression instead and didn't get any warning
0b1111111100000000000000000000000000000000000000000000000000000000
and
0b1000000010000000100000001000000010000000100000001000000010000000
The problem is that the 0bxxxx form is not standard C (As I read in this StackOverflow answer), therefore I am not allowed to use it.
I also tried
mask_left = (unsigned long long)9259542123273814144;
mask_top = (unsigned long long)18374686479671623680;
The compiler still tells me that the value is too large to be represened in a signed integer type. What am I doing wrong ? Is there any way to fix this at all ?
Implicitly, the integer literal is signed and of course the values are too big for a signed long long, so you need to let the compiler know that they have type unsigned, like this
mask_left = 9259542123273814143U;
mask_top = 18374686479671623680U;
Rewrite it with explicit size:
mask_left = 9259542123273814144uLL;
mask_top = 18374686479671623680uLL;
By writing it as (unsigned long long) 9259542123273814144 it means to take the integer and then cast it longer. Unfortunately, the integer is probably munged (by throwing away the higher bits to make it an int) and then increasing the size.
Signed integer literals cannot be larger than 2147483648. For a number larger than that, you need to add the LL prefix, which tells the compiler it is a long long. In your case, you want ULL as that designates an unsigned long long, which is what you're assigning to.

How Data Store in ARM processor

I'm newbie in ARM experiment and I have a problem with concept of data in this processor.
I ran into trouble. there is code to check timer interval:
// get the current timer 0 count
unsigned long Timer0_GetTimestamp(void)
{
return T0TC;
}
// check to see if a timestamp is in the past
// returns 1 if in the past, 0 if not
int Timer0_TimestampExpiredCk(unsigned long timestamp)
{
unsigned long now = T0TC;
if (now > timestamp)
{
if ((now - timestamp) < 0x80000000)
return 1;
else
return 0;
}
else
{
if ((timestamp - now) >= 0x80000000)
return 1;
else
return 0;
}
}
// pause for a specific number of milliseconds
void Timer0_Delay(unsigned long milliseconds) {
unsigned long timestamp = Timer0_GetTimestamp() + milliseconds;
while (!Timer0_TimestampExpiredCk(timestamp));
}
I have a problem with the number "0x80000000". Should we consider this number as a 2's complement or just binary ?
it is supposed, when the difference between two variable is Zero we change our flag. Correct me if I wrong.
Thank you
(your question has nothing to do with ARM, it is a language question).
what do you want that number to be? you can specify it 0x8000000UL will make it an unsigned long yes?
BTW if you are wanting 0x80000000 as an unsigned long then you can also just look at the msbit of the now-timestamp result
if((now-timestamp)&0x80000000)
return 0;
else
return 1;
and there is no ambiguity there.
or
return (~(now-timestamp))>>31;
Might need an &1 on the end of that if unsigned long is 64 bits, not if unsigned long is 32.
In C, the constant 0x8000000 would be represented as an unsigned int as long as int is 32 bits or greater. This because the compiler must choose the first type from the following list in which the constant can be represented:
int
unsigned int
long
unsigned long
long long
unsigned long long
(C99 standard section 6.4.4.1)
And 0x80000000 can't be represented as a 32 bit int, at least not in 2's complement.
Both of the variables being compared are unsigned int. I can't see any purpose in this comparison with 0x80000000. Surely to check if a timestamp is in the past you just need to do the comparison
return (now > timeStamp);
Your code returns true if the time stamp is in the past unless it is a very long way in the past i.e. more than 0x80000000 milliseconds. It also returns true if the timestamp is a long way in the future.
What's T0TC by the way? If it's a constant, your timer will never expire.

Weird Question regarding C integer type and printf() specifier

Alright i know this question might some weird , but still i wanted to demystify it.
1.)an int type in C can stores number in the range of -2147483648 to 2147483647.
2.)If we append an unsigned it front of it , the range would become 0 to 2147483647.
3.)The thing is , why do we even bother to use the keyword unsigned when the code below could actually works.
The Code:
#include <stdio.h>
int main(void)
{
int num = 2147483650;
printf("%u\n" , num);
return 0;
}
4.)As you see , i can still print out the integer as unsigned type if I use the %u specifier and it will print me the value 2147483650.
5.)Even if I create another integer type with value 50 and sum it up with num , although it's overflow but yet I still can print out the correct sum value by using %u specifier.So why unsigned keyword is still a necessity??
Thanks for spending time reading my question.
No, this is true only on certain platforms (where an int is 32-bit, 2's-complement).
No, in that case the range would be 0 to 4294967295.
That code exhibits undefined behaviour.
See 3.
See 2. and 3.
Considering only Q3, "Why do we bother to use unsigned", consider this program fragment:
int main(void) {
int num = MAX_INT;
num += 50;
printf("%u\n", num); /* Yes, this *might* print what you want */
/* But this "if" almost certainly won't do what you want. */
if(num > 0) {
printf("Big numbers are big\n");
} else {
printf("Big numbers are small\n");
}
}
We use "unsigned" because unsigned int behaves differently from int. There are more interesting behaviors than just how printf works.
Well, firstly the result of assigning an out-of-range number is implementation-defined - it doesn't have to give the value that will "work" when printed with the %u format specifier. But to really answer your question, consider this modification to your code:
#include <stdio.h>
int main(void)
{
int num = 2147483650;
unsigned num2 = 2147483650;
num /= 2;
num2 /= 2;
printf("%u, %u\n" , num, num2);
return 0;
}
(If 2147483650 is out of range of int on your platform, but within the range of unsigned, then you will only get the correct answer of 1073741825 using the unsigned type).
Wrong. The range is INT_MIN (which in 2 completment systems usually is -INT_MAX+1) to INT_MAX; INT_MAX and INT_MIN depends on the compiler, architecture, etc.
Wrong. The range is 0 to UINT_MAX which is usually INT_MAX*2 + 1
Unsigned integers have a different behaviour regarding overflow and semantics. In 2 complement there's one value undefined for signed integers (that is if only the uppermost bit is set, the rest zero), that has somewhat a double meaning. Unsigned integers can make use of the full range of bit patterns.
Here's an exercise: On a 32 bit machine compare the output of printf("%d %u", 0xffffffff, 0xffffffff);
Because unsigned integers behave differently than signed ones.

Resources