why does my variable has a greater value than I set? - arm

Nowadays I'm working on ARM R7 and I found a situation I can't understand why.
Here's my code
if ( i++ > 2048 )
{
panic(...); <----- here it has 2050 in its coredump.
}
When it gets panic'ed, it dumps the whole memory and I can load it up w/ T32.
By the way, the variable 'i' has 2050, not 2049.
I don't understand why it has such value.
Someone can explain why it does, please...
PS : not multi-threaded.

i++ returns the previous value of the variable (while ++i returns the new one). So, when i is 2049 (or any larger value), the condition is true and panic is called. When i was 2049 before, it will be 2050 after the if. It will always be incremented, regardless whether the condition was true or not. This is a fundamental rule in C, C++ and many other languages and has nothing to do with ARM or pipelines.

A. Don't you want to do while not if.
B. Where do you initialize i?

Related

What does an "extra" semicolon means? [duplicate]

This question already has answers here:
Two semicolons inside a for-loop parentheses
(4 answers)
Endless loop in C/C++ [closed]
(12 answers)
Closed 4 years ago.
I was searching for an explanation for the "double semicolon" in the code:
for(;;){}
Original question.
I do not have enough reputation to even leave a comment so I need to create a new question.
My question is,
What does an "extra" semicolon means. Is this "double semicolon" or "extra semicolon" used for "something else"?
The question comes from a person with no knowledge of programing, just powered on my first arduino kit and feel like a child when LED blinked.
But it is the reality that the questions, like general occurence, are radiating the actual knowledge of the person asking the question.
And beyond "personal preference" in using while(1) or for(;;) is it helpful in using for(;;) where you do not have enough room for the code itself?
I have updated the question.
Thank you for the quick explanation. You opened my eyes with the idea of not using anything in for loop = ). From basic high school knowledge I am aware of for loop so thank you for that.
So for(;;) returns TRUE "by default"?
And my last line about the size of the code?
Or it is compiled and using for or while actually does not affect the compiled code size?
A for loop is often written
int i;
for (i = 0; i < 6; i++) {
...
}
Before the first semicolon, there is code that is run once, before the loop starts. By omitting this, you just have nothing happen before the loop starts.
Between the semicolons, there is the condition that is checked after every loop, and the for loop end if this evaluates to false. By omitting this, you have no check, and it always continues.
After the second semicolon is code that is run after every cycle, before that condition is evaluated. Omitting this just runs additional code at that time.
The semicolons are always there, there is nothing special about the face that they are adjacent. You could replace that with
for ( ; ; )
and have the same effect.
While for (;;) itself does not return true (It doesn't return anything), the second field in the parentheses of the for always causes the loop to continue if it is empty. There's no reason for this other than that someone thought it would be convenient. See https://stackoverflow.com/a/13147054/5567382. It states that an empty condition is always replaced by a non-zero constant, which is the case where the loop continues.
As for size and efficiency, it may vary depending on the compiler, but I don't see any reason that one would be more efficient than the other, though it's really up to the compiler. It could be that a compiler would allow the program to evaluate as non-zero a constant in the condition of a while loop, but recognise an empty for loop condition and skip comparison, though I would expect the compiler to optimize the while loop better. (A long way of saying that I don't know, but it depends on a lot.)

Subscripts going out of range in an array

Here the subscripts of the array are out of range.
int a[10], i;
for (i = 1; i <= 10; i++)
a[i] = 0;
printf("India");
The output is an infinte loop and printf statment doesnt get executed. here's what written in K N King:
When i reaches 10. the program stores 0 into a [10] . But a [10] doesn’t exist.
so 0 goes into memory immediately after a [9] . If the variable i happens to follow
a [9] in memory—as might be the case—then i will be reset to O. causing the
loop to start over.
Can anyone explain it ?
The idea that this will form an infinite loop is based on an assumption about how the variables will be laid out in memory. In particular, it assumes that because i is defined immediately after a, that it will also be allocated in memory immediately after a.
That's certainly not guaranteed, but it equally certainly could happen. If it does, then the write to a[10] may actually overwrite i. Since it's writing 0 into the nonexistent a[10], doing so actually writes 0 into i. Then when the condition in the loop checks that i <= 10, that's true, so the loop continues -- and each time i gets to 10, it's immediately overwritten with 0 before the loop condition is evaluated, so the loop re-starts from the beginning.
As far as either the C or C++ standard cares, it's just undefined behavior--when the code writes past the end of the array anything can happen. It might do what somebody expects, or might might do something entirely different and unrelated that doesn't seem to make sense at all. The compiler is free to emit code that does pretty much anything in such a circumstance (or it could, for example, diagnose it as an error, and emit no code at all).
To give some idea of what conforming behavior could be: early versions of gcc had code to detect a specific case of implementation-defined behavior (pretty much like undefined behavior, except the implementation has to document what it does). In this case, the documented behavior was fairly complex. The compiler would attempt to do each of the following in order (and stop at the first one that succeeded):
run nethack (a game)
run rogue (another game)
start emacs, and have it execute a towers of hanoi simulation
print out "You are in a maze of twisty little passages, all alike".
I could be getting the order of those a bit wrong (this was a long time ago), but you get the idea. The result had nothing to do with anything a reasonable person would be likely to expect.

How to check if any one of several pointers is null?

I have several pointer/integer variables and I want to check if any of them is 0. Right now I compare each to 0 in a large if statement that would short circuit once it hits one that is 0. I was wondering if there is any more clever or faster way of accomplishing this.
It doesn't really matter. Even if you'd stack all pointers up and loop over this array or if you or-ed all values.. you'd still have to do that one after another. And if you have something like this if( a != 0 && b != 0 && .. && z != null) the compiler will convert that to as many instructions as it will need in all other cases.
The only thing you might could save using an array which you e.g. you loop over is maybe memory at some point but I don't think this is what you were looking for.
No there is not. Think about it: to really be sure that not a single one of your values is zero, you absolutely have to look at each an every one of them. As you correctly noted, it is possible to short-circuit, one a zero-value has been found. I would recommend something similar to this:
int has_null = -1;
for(int i=0; i < null_list_len && has_null &= null_list[i]; ++i)
;
if(has_null)
//do stuff
You can improve the run time, if you have more assumptions about the values you are testing. If, for example you knew, that the null_list array is sorted, you only have to check wether the very first entry is zero, as a non-zero entry would imply that all other values are also greater than zero.
Well, you could code whatever it is that sets the vars to zero to ensure that a common boolean is set to 'true'.
Checking would then be a matter of testing one boolean, no matter how many vars there are. If the bool is true, then you can do a sequential check, much as you are doing now.
That may, or may not, be possible, faster, or more efficient, overall, (or not).

1 = false and 0 = true?

I came across an is_equals() function in a c API at work that returned 1 for non-equal sql tables (false) and 0 for equal ones (true). I only realized it after running test cases on my code, one for the positive example and one for the negative and they both failed which at first made little sense. The code in the API does not have a bug as the output was recorded correctly in its documentation.
My questions - are there upside down worlds / parallel universes / coding languages where this logical NOTing is normal? Isn't 1 usually true? Is the coder of the API making an error?
It is common for comparison functions to return 0 on "equals", so that they can also return a negative number for "less than" and a positive number for "greater than". strcmp() and memcmp() work like this.
It is, however, idiomatic for zero to be false and nonzero to be true, because this is how the C flow control and logical boolean operators work. So it might be that the return values chosen for this function are fine, but it is the function's name that is in error (it should really just be called compare() or similar).
This upside-down-world is common with process error returns. The shell variable $? reports the return value of the previous program to execute from the shell, so it is easy to tell if a program succeeds or fails:
$ false ; echo $?
1
$ true ; echo $?
0
This was chosen because there is a single case where a program succeeds but there could be dozens of reasons why a program fails -- by allowing there to be many different failure error codes, a program can determine why another program failed without having to parse output.
A concrete example is the aa-status program supplied with the AppArmor mandatory access control tool:
Upon exiting, aa-status will set its return value to the
following values:
0 if apparmor is enabled and policy is loaded.
1 if apparmor is not enabled/loaded.
2 if apparmor is enabled but no policy is loaded.
3 if the apparmor control files aren't available under
/sys/kernel/security/.
4 if the user running the script doesn't have enough
privileges to read the apparmor control files.
(I'm sure there are more widely-spread programs with this behavior, but I know this one well. :)
I suspect it's just following the Linux / Unix standard for returning 0 on success.
Does it really say "1" is false and "0" is true?
There's no good reason for 1 to be true and 0 to be false; that's just the way things have always been notated. So from a logical perspective, the function in your API isn't "wrong", per se.
That said, it's normally not advisable to work against the idioms of whatever language or framework you're using without a damn good reason to do so, so whoever wrote this function was probably pretty bone-headed, assuming it's not simply a bug.
It may very well be a mistake on the original author, however the notion that 1 is true and 0 is false is not a universal concept. In shell scripting 0 is returned for success, and any other number for failure. In other languages such as Ruby, only nil and false are considered false, and any other value is considered true, so in Ruby both 1 and 0 would be considered true.
Simple Answer
0 = false
1 = true
I'm not sure if I'm answering the question right, but here's a familiar example:
The return type of GetLastError() in Windows is nonzero if there was an error, or zero otherwise. The reverse is usually true of the return value of the function you called.
Generally we think that 0 is false and 1 is true

Why return a negative errno? (e.g. return -EIO)

Another simple example:
if (wpa_s->mlme.ssid_len == 0)
return -EINVAL;
Why the unary minus? Is this (usually) done for functions that return >0 on success and <(=)0 on failure, or is there some other reason?
First, this isn't really a C thing. You're looking at a function that is written in C for some purpose. The same conventions could be used in any language.
Back in my old Unix days, there was something of a convention that 0 meant success, a positive number meant minor problems, and a negative number meant some sort of failure. Therefore, there was also a sort of convention of if (foo() >= 0) { /* success of a sort */ }.
This was doubtless related to Unix process return codes, where 0 was success.
That's basically the reasons. Lots of functions have lots of "good" positive results, so that leaves the negative values for error codes.
C / POSIX error codes are a bit "historically grown," so there's not much sense in trying to attribute too much rhyme or reason to them.
Many more modern languages throw exceptions for errors so that they don't have to hijack part of their possible response range for error codes. Of course there are trade-offs either way.
Your understanding is broadly correct. The obvious interpretation is the right one.
The standard convention is slightly different than your formula, however.
In Unix, a program that exits with 0 status tests as true or success to CLI-level utilities like the shell. In the library, -1 is usually an error return.
This leads to a general paradigm where >= 0 means good and < 0 means error. None of this is set in stone.
BTW, this might be classified as the sentinel pattern and you could call it a sentinel return. It's actually a combination of a sentinel "value" and an error code, and it's easier to type and easier to make thread-safe than returning an error code in one place and a sentinel value for error in another.
Wikipedia reports that a sentinel value is used to terminate a loop, but I would think that a function return would be a far more common instance. No one is precisely in charge of these definitions.
From an optimization perspective, using negative numbers allows Unix-based kernels to check for an error code using only one comparison instead of two.
Functions in the kernel frequently return error codes in place of pointers. This means that the error codes can't overlap with valid pointer addresses, so they'd basically have to be either the lowest unsigned values (>= 0) or the highest ones (<= unsigned max).
Checking pointer values for NULL and for error codes are extremely common operations, so it makes sense to optimize them.
Typically the bottom values < 0x8000 are NULL and the top values are error codes (remember that -1 is stored as 0xff...ff, the maximum possible unsigned value).
This means that you can use one comparison to check for each:
NULL if x <= 0x8000 (true for 0 to 0x8000)
ERRNO if x >= (unsigned long)(-MAX_ERRNO) (true for -1 to -MAX_ERRNO)
You can see this happening in Linux's err.h file.

Resources