Warning comparison integer and pointer [duplicate] - c

This question already has answers here:
Is (4 > y > 1) a valid statement in C++? How do you evaluate it if so?
(5 answers)
Closed 6 years ago.
int b[5] = {1,2,3,4,5};
int *s = &b[0];
int *p = &b[1];
int *q = &b[2];
int *r = &b[2];
My question is when I compare p < q < r using if( p < q < r), I got the warning message.
What I thought is, first of all, (p < q) == True, so it's impossible to compare boolean with integer( address value of r). However, when True is considered as integer, it's 1. Right? So, 1 < r might make sense, in my guess.
What's wrong with my thought?

1 < r doesn't work because 1 is an integer and r is a pointer. Thus the warning.
My guess is you (a) meant to dereference the pointers, and (b) need to replace the chained comparisons with &&.
if (*p < *q && *q < *r)

You seem to be under the impression that the expression p < q < r translations to "p is less than q, q is less than r", which would be typical of a mathematical notation.
However, the C programming language doesn't necessarily follow mathematical conventions. What p < q < r actually translations to is p < q, which might be 0 or 1 depending upon whether that's false or true, followed by either 0 < r or 1 < r based on that previous difference.
As another user has pointed out, the proper way to write "p is less than q and q is less than r" is p < q && q < r.

Change your condition from:
if(p < q < r) {}
To:
if(p < q && q < r) {}

Related

Found 2 liner C solution with ',' operator in for loop, can someone explain given comma operator statement?

Explanation:
I've following problem statement at hand, I came across an interesting 2 liner, C solution for it under leedcode discussion section. I tried to decompose it to understand what it means, and except one small line, I understood the rest. My question is at the end.
Leetcode Problem Statement:
Given an array arr of positive integers sorted in a strictly increasing order, and an integer k.
Find the kth positive integer that is missing from this array.
Example 1: Input: arr = [2,3,4,7,11], k = 5
Output: 9
Explanation: The missing positive integers are
[1,5,6,8,9,10,12,13,...]. The 5th missing >>positive integer is 9.
Example 2:
Input: arr = [1,2,3,4], k = 2
Output: 6
Explanation: The missing positive integers are [5,6,7,...].
The 2nd missing positive integer is 6.
Constraints:
1 <= arr.length <= 1000
1 <= arr[i] <= 1000
1 <= k <= 1000
arr[i] < arr[j] for 1 <= i < j <= arr.length
Two liner C solution:
int findKthPositive(int* arr, int arrSize, int k){
for (int arrCurrIndex = 0, counter = 1 ; (k && (arrCurrIndex < arrSize) ? ((arr[arrCurrIndex] != counter) ? k-- : ++arrCurrIndex) : k--) || (k = counter-1, 0) ; counter++);
return k;
}
For reference: Following is a similar algorithm that's being deployed, but its just cleaner to understand.
int findKthPositive(int* arr, int arrSize, int k){
for (int counter=1, arrCurrIndex=0; counter<10000; counter++) {
// exceed arr limits
if (arrCurrIndex < arrSize) {
if (counter == arr[arrCurrIndex]) { // found element in array
index++;
continue;
}
}
// missing element
k--;
if (k==0) {
return counter;
}
}
return 0;
}
My question:
What does following line in solution #1 means exactly?
(k = counter-1, 0)
======UPDATE ON ANSWER=======
I modified solution #1 in question slightly to make it more readable. It highlights what is going on with the given statement in question.
Here is the modified solution:
int findKthPositive(int* arr, int arrSize, int k){
// move counter out of the foor loop
int counter=1;
for (int arrCurrIndex = 0;
(k && (arrCurrIndex < arrSize) ?
((arr[arrCurrIndex] != counter) ? k-- : ++arrCurrIndex)
: k--); counter++);
return counter-1;
}
The binary comma operator , evaluates the first operand, discards the result and then evaluates the second one.
In the expression you posted we have
... || (k = counter-1, 0) ;
so counter-1 is actually assigned to k but its evaluation (k itself) is discarded so that 0 is used. Why 0? Because it is the neutral operand for logic or operator ||. In fact
X || 0 ==> X
In other words we have the expression
stuff_at_the_left || (k = counter-1, 0 )
that is evaluated as
stuff_at_the_left || 0
And since 0 is the neutral operand in logical or, the final evaluation is stuff_at_the_left.
The purpose of this weird expression is to cheat: the author at some point needed to assign that value to k but without adding more lines "ruining" the one liner. So they included the assignment in the logical expression making it neutral with comma operator combined with or operator's neutral operand.We also have to say that the assignment k=counter-1, 0 is performed only if all stuff_at_the_left is evaluated as 0 (due to the short circuiting nature of logical operators in C). The resulting expanded code is
if (!stuff_at_the_left)
k= counter-1;
Note: the comma operator has the lowest precedence among all the operators in C, and that's why the assignment is performed at first.

updating values in array in C

I have an array with values initialized to an integer value. When I try to change the values and print to file, the code compiles but returns a "segmentation fault" error upon execution. Any thoughts would be much appreciated!
int theArray[50];
...//code setting the array values to zero
int i;
for(i = 0; i < 50; i++)
{
...//code setting int "p" to some number between -100 and 100
if (p < 25 || p > -25)
{
int temp = p + 25;
int currentVal = theArray[temp];
theArray[temp] = currentVal + 1;
}
}
When I take out the step changing the "currentVal" there is no segmentation fault. Thanks in advance!
Your condition is wrong
if (p < 25 || p > -25)
if p is 1000, it will enter this if, as well as when p is -1000. You need the AND logical operator
if (p < 25 && p > -25)
Also, since your valid indices range from 0 to 49 inclusive, I think one of the operators must include equality, namely:
if (p < 25 && p >= -25)
You've never declared the size of the array, so it's an array of length 0 (no ints have been allocated). Therefore, then you try to initialize a part of the array, you get a segmentation fault due to accessing memory in which you are not allowed to.
To fix this, give the array a compile-time constant array size:
int theArray[50];
...//code setting the array values to zero
int i;
for(i = 0; i < 50; i++)
{
int currentVal = theArray[i]; // make sure you've initialized the array before doing this
theArray[i] = currentVal + 1;
}
While giving the input you must have entered integers more than the size of your array theArray[] i.e, 50.That is why your compiler is showing you segmentation fault.
I am almost sure it be if(p<25 && p>-25)... You probably confused the logical operators.
Isn't this is what you are trying to do ?
int i;
for(i = 0; i < 50; i++) {
theArray[i] += 1;
}
Does this not work for you ?
EDIT
if (p < 25 || p > -25) will evaluate to true for values such as -50, -26, etc because of short circuit evaluation of ||, meaning p < 25 will be evaluated first and if found true the other condition will not be evaluated.
For numbers like 50, the second condition will evaluate to true and temp will again go out of bounds for theArray
In either case, you will see Segmentation fault
if (p < 25 && p > -25) should help you.

ACSL - Can't prove function [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to prove this function, but in vain. I'm also using another function, but I proved it.
Could anyone help me?
I'm using Frama-C Sodium version with Alt-ergo 3 as prover.
Given a not-empty string x. An integer number p such that
0 < p ≤|x| is meant to be "a period of x" if
x[i] = x[i + p]
for i = 0, 1, ... , |x| − p − 1.
Note that, for each not-empty string, the length of the string
is a period of itself. In this way, every not-empty string
has got at least one period. So is well formed the concept of minimum
period of string x, denoted by per(x):
per(x) = min { p | p is period of x }.
Write a C function
unsigned per(const char x[], unsigned l)
that, given a string x of length l, returns per(x).
Here is the code and the specifications I have written so far:
/*#
requires l > 0;
requires p >= 0;
behavior zero:
assumes p == l;
ensures \result == 1;
behavior one:
assumes l != p && (l%p) == 0;
assumes \forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p];
ensures \result == 1;
behavior two:
assumes l != p && (l%p) == 0;
assumes !(\forall int i; 0 <= i < l-p-1 ==> x[i] == x[i+p]);
ensures \result == 0;
behavior three:
assumes p != l && l%p != 0;
ensures \result == 0;
complete behaviors;
disjoint behaviors;
*/
unsigned has_period(const char x[], unsigned int p, unsigned l) {
if (p == l) return 1;
if ((l % p) != 0) return 0;
/*#
loop assigns i;
loop invariant \forall int j; 0 <= j < i ==> (x[j] == x[j+p]);
loop invariant i <= l-p-1;
loop invariant i >= 0;
*/
for (int i = 0 ; i < l-p-1 ; ++i) {
if (x[i] != x[i + p])
return 0;
}
return 1;
}
/*
predicate has_period(char* x, unsigned int p, unsigned l) =
\forall int i; i < (l-p-1) ==> x[i] == x[i+p];
*/
/*#
requires l > 0;
requires \valid(x+(0..l-1));
ensures 1 <= \result <= l;
ensures \forall unsigned int i; i < (l-\result-1) ==> x[i] == x[i+\result];
ensures \forall unsigned int p; 1 <= p < \result ==> !(\forall int i; i < (l-p-1) ==> x[i] == x[i+p]);
*/
unsigned per(const char x[], unsigned l) {
int p = 1;
/*#
loop assigns p;
loop invariant 1 <= p <= l;
loop invariant \forall unsigned j; 1 <= j < p ==> !(\forall int i; i < (l-j-1) ==> x[i] == x[i+j] || (l%p) == 0);
loop invariant p >= 0;
*/
while(p < l && !has_period(x,p,l))
++p;
return p;
}
It would have helped if you had told us what your specific issue was, instead of a generic "it doesn't work", but here are some points:
Your contracts are lacking assigns clause. These are not optional when using WP, especially for functions like has_period that are called within your development. WP needs those clauses to know which locations might have changed during the call, and by taking the complement, which locations have stayed the same.
You have given a nice semi-formal definition of what a periodic string is. You should use that to define an ACSL predicate periodic (taking the same arguments as your C function has_period), and write your specifications according to this predicate. This will simplify your annotations a lot. In particular has_period does not need 4 behaviors: if periodic holds it must return 1, if periodic does not hold, it must return 0.
Using -wp-rte leads to a bunch of unproved obligations. Depending on your assignment, you might want to strengthen your specifications, especially regarding the validity of the location pointed to by x.

If statement being skipped

In this method I am looking to see if a string appears in word search. Since a string can appear in any direction I have methods like the following which check those directions:
Currently my code is giving a segmentation fault when run. This is happening because the first if statement in my method is being skipped according to gdb.
The grid I am working with looks like this:
a r e o
o n l y
o d d a
The values of x, y and str at runtime (just before segfault) are:
x = 0;
y = 0;
str = "add"
Now strlen(str) evaluates to 3 and x - 3 evaluates to -3.
-3 < 0 would evaluate true and quits my method. Unfortunately the if statement at the start of the method is skipped at run time. Anyone know what is going on?
Furthermore I'll add that if I change the first line of my grid to:
q r e o
I get proper results.
Here is the method:
bool checkNorth (int x, int y, string str) {
//Deal with trival case and avoid array out of bounds/checking silly things
if (x-strlen(str) < 0){
return false;
}
//for each character in str
for (int i = 0; i < (strlen(str)); i++){
//If the character above in the grid is the next character in the string
if (grid[x-i][y].letter == str[i]){
//keep going
continue;
}else{
//It ain't north
return false;
}
}
//It's north
return true;
}
Since strlen() returns a value of type size_t, which is unsigned, then you compute x - 3 the computation is done on unsigned values, and with unsigned arithmetic, 0 - 3 is a large positive value, and is never less than zero. In fact, since the comparison is for an unsigned quantity less than 0, but unsigned quantities can never be negative, the compiler can optimize the entire if test and the following return completely away.
You can fix the problem by changing:
if (x-strlen(str) < 0){
to:
if (x < strlen(str)) {
Note that your loop is somewhat inefficient. You have:
for (int i = 0; i < (strlen(str)); i++){
This recomputes strlen(str) on each iteration. You could write:
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
This guarantees that the length is only computed once, which is sufficient unless you're modifying the string somewhere in the function, or one of the functions it calls.

Are multiple conditions allowed in a 'for' loop?

The following code runs without giving any errors or warnings:
#include <stdio.h>
int main(){
int i, j;
int p = 0, q = 2;
for(i = 0, j = 0; i < p, j < q; i++, j++){
printf("Hello, World!\n");
}
return 0;
}
However, the book Let Us C (Yashwant Kanetkar) says that only one expression is allowed in the test expression of a for loop (see page 115 of the book).
I am not sure of the standard. Are multiple expressions allowed in the test expression of a for loop?
I surely can join the two expressions, but I was dumbstruck when I found the above code on this website. Is this valid C code or not?
The condition
i < p, j < q
is allowed but probably isn't what was intended as it discards the result of the first expression and returns the result of j < q only. The comma operator evaluates the expression on the left of the comma, discards it then evaluates the expression on the right and returns it.
If you want to test for multiple conditions use the logical AND operator && instead
i < p && j < q
You can link them together with boolean and (&&)
for(i = 0, j = 0; (i < p) && (j < q); i++, j++){
The above won't print out anything in the loop because the (i < p) condition fails immediately as i & p are both the same value (0).
Update: Your example is valid (but silly) C because if you start i=30 your loop will still execute 2 times, because the first result in a comma separated list is ignored.
If you want to test both conditions, use the && operator.
What is happening in your code is related to how the comma operator , works.
Both i < p and j < q are evaluated, but only the result of the 2nd expression j < q is checked by the for loop.
for(i = 0, j = 0; i < p && j < q; i++, j++){
Even I have read That Book by Mr Yashwant Kanetkar. It do says that only one condition is allowed in a for loop, however you can add multiple conditions in for loop by using logical operators to connect them. In other books that I have Read Along time Ago, said that only one condition is allowed.

Resources