How to fix 'warning: large integer implicitly truncated to unsigned type [-Woverflow]'? - embedded

I created these macros to execute an arithmetic operation:
#define CLK_FREQ 8U
#define I2C_BMP180 I2C1
#define I2C_CLK_FREQ CLK_FREQ
#define I2C_GET_CCR_SM(i2c_speed) (500000U * I2C_CLK_FREQ / ((unsigned int)(i2c_speed)))
After compilation, I get this warning:
src\main.c:11:35: warning: large integer implicitly truncated to unsigned type [-Woverflow]
#define I2C_GET_CCR_SM(i2c_speed) (500000U * I2C_CLK_FREQ / ((unsigned int)i2c_speed))
^
How can I fix this?

The equation is mixed both signed and unsigned parameter. Please try following:
#define CLK_FREQ 8U
#define I2C_CLK_FREQ CLK_FREQ
#define I2C_GET_CCR_SM(i2c_speed) (1000000U * I2C_CLK_FREQ / (2U * (unsigned int)i2c_speed))
The key here is that the result should be unsigned and therefore it is better to convert all to unsigned. Compiler might have problem on knowing whether you want a use signed or unsigned

You should ensure type/sign agreement in your macro, and also coerce the i2c_speed expression over which you have no control:
#define CLK_FREQ 8u
#define I2C_CLK_FREQ CLK_FREQ
#define I2C_GET_CCR_SM(i2c_speed) ((500000U * I2C_CLK_FREQ) / (unsigned)(i2c_speed))

Related

If/else macros behaving differently with BOOL than with numbers [duplicate]

This question already has answers here:
Preprocessor macro and BOOL weirdness
(2 answers)
Closed 7 years ago.
I have the following code which works properly:
#define TEST 0
#if TEST == 1
#define URL #"example.com"
#else
#define URL #"not-example.com"
#endif
So in this scenario, URL will be not-example.com as expected.
Now, I want to use BOOL instead of 0 and 1. However, when I try the following code, it gives me the wrong answer:
#define TEST NO
#if TEST == YES
#define URL #"example.com"
#else
#define URL #"not-example.com"
#endif
This gives me URL equal to example.com. The same answer is given if TEST is set to YES.
Why is using a BOOL different than using a number in macros?
The preprocessor is the standard C preprocessor and works on very limited expressions made up from numeric constants. Any non-macro identifier in a preprocessor expression is treated as having the value 0.
The Objective-C NO is not a macro for a number but for _objc_no, and that is not a number but a non-macro identifier - so in a conditional expression it would be treated as 0. Same for YES.
So your:
#if TEST == YES
turns out to be:
#if 0 == 0
whether TEST is YES or NO.
For more details see C Preproccesor: Conditionals (From GCC, but the same applies to Clang/Xcode and other C compilers.)

Objective-C #define macro evaluation incorrect within if statement

I am confused about why the following #define macros are not evaluating as expected when used in the following if statement:
#define kOffsetX 2048.0
#define kPositionX (screenSize.width * (kOffsetX/2048.0))-10.0
CGSize screenSize = [CCDirector sharedDirector].winSize;
float potentialPosition = 486.86f;
float playersFieldOffset = 1.0;
if ((potentialPosition - kPositionX) * playersFieldOffset > 0.0) {
Note that kPositionX evaluates to 470.0. The if statement evaluates to FALSE when clearly 486-470 is greater than zero. However, if I put parenthesis around kPositionX, then the if statement properly evaluates to TRUE.
Why is this happening? Is this an improper way to use a #define? If so, what should I be doing?
The preprocessor just replaces all macros by their definition, so
potentialPosition - kPositionX
is expanded to
potentialPosition - (screenSize.width * (2048.0/2048.0))-10.0
which, when evaluated at runtime, gives
486.86 - 480 - 10 = -3.14 < 0
You should always enclose expressions in macros in parentheses:
#define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)
so that the expansion gives
potentialPosition - ((screenSize.width * (2048.0/2048.0))-10.0)
which is what you expect.
This is (one of the) disadvantages of preprocessor macros. Alternatively, you can
use for example (inline) functions, see Inline functions vs Preprocessor macros
for more information.
Whenever using #define, make sure to wrap the entire contents of the #define in parentheses. This will prevent any incorrect order of operations calculations from happening. So change your #defines to
#define kOffsetX (2048.0)
#define kPositionX ((screenSize.width * (kOffsetX/2048.0))-10.0)
#define macros are literal expressions! After any arguments are spliced in (and you aren't using any arguments for this macro), the macro is basically inserted directly into the code. So, while you are expecting
if ((potentialPosition - kPositionX) * playersFieldOffset > 0.0)
to turn into
if ((potentialPosition - (answer of kPositionX) * playersFieldOffset > 0.0)
it actually turns into
if ((potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0) * playersFieldOffset > 0.0)
Which evaluates incorrectly. You could solve this by either surrounding the whole macro in parentheses.
#define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)
or, as you said, surrounding kPositionX with parentheses
if ((potentialPosition - (kPositionX)) * playersFieldOffset > 0.0) {
Also, as a general rule of good practice, macros are usually written in all capitals, with underscores (_) showing a break between words. #define MACRO_NUMBER_ONE
Macros work by string substitution. Your macro kPositionX is of the form (a) - b so when you use it in the subexpression (potentialPosition - kPositionX) the result is:
(potentialPosition - (screenSize.width * (kOffsetX/2048.0)) - 10.0)
in which 10.0 is subtracted from potentialPosition. Probably you wanted:
(potentialPosition - ((screenSize.width * (kOffsetX/2048.0)) - 10.0))
note the extra parentheses - in which 10.0 is added to potentialPosition.
You must always remember that macros use string substitution when defining them, and any macro containing an expression should have outer parentheses to avoid problems:
#define kPositionX ((screenSize.width * (kOffsetX/2048.0)) - 10.0)

Concat two macros in Objective-C

I'm trying to concatenate two values each defined as macro. At this moment I've:
#define VAL1 #"im/"
#define VAL2 #"test"
#define GLUE_IN(x,y) (x ## y)
#define GLUE(x,y) GLUE_IN(x,y)
when I use it in code:
[array addObject:GLUE(VAL1, VAL2)];
it produces me an error: Pasting formed '"im/"#', an invalid preprocessing token
I'm aware that it may be solved by:
#define GLUE(x,y) [NSString stringWithFormat:#"%#%#",x,y]
however I'm curious is it possible to achieve this same result using preprocessor?
## concatenates tokens, not strings, which causes an invalid resulting token, and in this case is entirely un-necessary since #"im/" #"test" - being compile time string constants - will be appended anyway. Just do;
#define GLUE_IN(x,y) (x y)
...which will result in
[array addObject:#"im/" #"test"]
...and things should work well.
I'm not gonna ask why you ever need it, but here is possible solution:
#define VAL1 im
#define VAL2 test
#define STR2(x) #x
#define STR(x) STR2(x)
#define GLUE_IN(a,b) a##b
#define GLUE(x,y) GLUE_IN(x,y)
…
NSString *val1 = #(STR(GLUE(VAL1, VAL2)));
NSString *val2 = #"another " #"test";
NSLog(#"%#, %#", val1, val2);
It gives you
imtest, anothertest
However, you'll have some troubles with a slash sign. If I were you, I'd prefer another way.

scanf in objective c returns weird result

The following returns an odd result in objective c.
#import <Foundation/Foundation.h>
#import <math.h>
#import <stdio.h>
#import <string.h>
char risk[2];
char gen1[1];
printf("Enter gender: ");
scanf("%s",gen1);
printf("Enter risk: ");
scanf("%s",risk);
And I get as gen1 the result of gen1 + risk instead of just gen1. In other words if gen1 = "m" and risk = "ns" then I'm getting gen1 = "mns" instead of just "m".
In a previous version this worked just fine.
Recently updated OS X to 7.8 along with the new preview XCode.
Not sure what I'm doing wrong here.
Thanks all,
Lou
You have to make room for the terminating NUL character:
char risk[3];
char gen1[2];
The probable reason for gen1 being "mns" is that allocated on the stack immediately after risk, and scanf overwrites the terminating NUL chatacter of gen1, effectively concatenating it with risk.

"strnset" is unable to be use in objective-c?

"strnset" is standard-c, (visual c++) and should work in objective-c.
But it doesn't recognize it.
What library am I missing? I have tried: stdio.h and string.h... both don't do it.
what would work in its place where I am given a char array and I want to create: n * characters to be placed in it?
example: _strnset(data, '8', 12); will yield -> data = "888888888888"
Use memset() instead. strnset is not part of the standard "C" library.
What property does strset have over memset that you are interested in?
NAME
memset -- fill a byte string with a byte value
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <string.h>
void *
memset(void *b, int c, size_t len);
DESCRIPTION
The memset() function writes len bytes of value c (converted to an
unsigned char) to the byte string b.
RETURN VALUES
The memset() function returns its first argument.
strnset is actually not a standard C function. It's not present in the GCC headers.