When I use a pointer in ternary operator if condition is true it executes exp3
#include <stdio.h>
int main(){
int a,b;
printf("Enter first number:");
scanf("%d",&a);
printf("Enter second number:");
scanf("%d",&b);
printf("Address of a:%u \n",&a);
printf("Address of b:%u \n",&b);
int *ptr=&b;
// when i use pointer in ternary operator if condition is true it execute exp3
// problem in this line
(*ptr++) > (*ptr) ? printf("\n %d is the maximum number",b):printf("\n %d is the maximum number",a);
(a>b) ? printf("\n %d",a) : printf("\n %d",b);
return 0;
}
There are several issues in your code that cause undefined behaviour (UB). The first is that you are using pointer arithmetic inappropriately. Operations like incrementing, decrementing and comparisons are only really useful on pointers to elements of arrays. In your case, neither a nor b is an array (although, from the compiler's perspective, they can be treated as single-element arrays), so there is no obligation on the compiler to follow any specific relative memory arrangement for those variables: they could be adjacent in memory, or separated by any number of bytes; and, even if they are adjacent, they could be "either way round" (that is, either a or b could be in the lower address).
We can create a 'quick workaround' in your code for this, by declaring an actual array and then make the a and b tokens aliases for elements of that array:
// int a, b;
int data[2];
#define a (data[0])
#define b (data[1])
Another cause of UB is the use of the wrong printf format specifier when showing your pointers; pointers should be printed using the %p specifier and, even then, should really be cast to void* when passed as arguments to printf:
printf("Address of a:%p \n", (void*)&a);
printf("Address of b:%p \n", (void*)&b);
But the third – and perhaps most important – source of UB occurs in the "condition" expression of your conditional ('ternary') operator: the (*ptr++) > (*ptr) comparison.
For this expression, the C Standard does not specify which of the operands of the > is evaluated first (i.e. the > operator is not a sequence point). So, expanding how the compiler might interpret this, using intermediate variables, we could get this:
T1 = (*ptr++); // T1 will get the value of "a", then "ptr" is incremented
T2 = (*ptr); // T2 will get the value of "b"
if (T1 > T2) ... // This will now be equivalent to the "a > b" comparison
Alternatively, the compiler would be equally entitled to do this:
T1 = (*ptr); // T1 will get the value of "a"
T2 = (*ptr++); // T2 will ALSO get the value of "a" and THEN 'ptr' is incremented
if (T1 > T2) ... // This will now be equivalent to the "a > a" comparison - which is wrong
We can resolve this UB by explicitly using intermediate variables like those above:
int T1 = *ptr++;
int T2 = *ptr;
T1 > T2 ? printf("\n %d is the maximum number", b) : printf("\n %d is the maximum number", a);
But note, even then, your code will show the wrong answer, because of the way the post-increment is applied (that is, after the value of *ptr has been assigned to T1).
If you must use pointers in your code, then avoid the post-increment and just use a simple addition to get the address of b (or the second element) and thus leaving ptr unchanged when using it to refer to a (the first element):
*(ptr+1) > *ptr ? printf("\n %d is the maximum number", b) : printf("\n %d is the maximum number", a);
Related
This question already has answers here:
C - how to convert a pointer in an array to an index?
(1 answer)
Pointer subtraction confusion
(8 answers)
Do pointers support "array style indexing"?
(1 answer)
Closed 3 years ago.
This is my code, which can find highest number in an array by the pointer.
#define ELTS 5
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, *high, *p;
int array[ELTS]={200,34,78,600,45};
high=array;
p=array;
for ( i=1; i< ELTS; i++ ) {
p++;
if (*p > *high) high = p;
}
printf("the highest number is %d \n", *high);
printf("at address %p \n", high);
printf("index %ld \n", high);
printf("index %ld \n", array);
printf("at index %ld of array \n", high-array);
exit(0);
}
I also need to find the index number of this number, I did some research online. and find out I can use printf("at index %ld of array \n", high-array); to get the index of the highest number.
However, I don't understand how that works, can anyone explain it to me?
In high-array, high is the address of the element you are interested in, and array is the address of the first element in the array. (array actually identifies the array, but, when used in this expression, it is automatically converted to the address of the first element.) Then, with the - operator, the two addresses are subtracted.
When addresses are subtracted, C produces a result measured in units of array elements. So, even if the array addresses are measured in bytes, the compiler computes a result by subtracting the pointers (to get the difference in bytes) and then dividing by the number of bytes in an element (to get the difference in elements).
Thus, the result of high-array is the number of elements from the start of the array to the element pointed to by high, and that is the index of that element.
(In some C implementations, the pointers might not be measured in bytes and might not be simple one-number addresses. Regardless, the C implementation performs whatever operations are necessary to produce a result that is a number of elements.)
Notes
To print pointers, convert them to void * and print them with %p:
printf("index %p \n", (void *) high);
To print the difference of two pointers, use %td:
printf("at index %td of array \n", high-array);
Use the pointer arithmetic. The index is calculated like
high - array
The difference contains the number of elements of the type int between these two pointers.
Consider for example this statement from your program
p++;
After this statement the pointer points to the next element of the array. This statement can be rewritten like
int *q = p;
p = p + 1;
So p - q is equal to 1.
I understand that in C programming, 'scanf' is used with '&' for all variable tyles (int, float, char, ..) except string. Here is my program code. In front of 'scanf', why isn't '&' needed? And may I know more about scanf?
#include <stdio.h>
#define M 10
int main()
{
int i, n, sum = 0;
int a[M];
do{
printf("Input a positive number less than %d \n",M);
scanf("%d", &n);
}while (!(n >0 && n < M));
printf("Input %d numbers \n",n);
for(i=0; i<n ; i++){
scanf("%d",(a+i));
sum += *(a+i);
}
printf("Sum = %d \n",sum);
}
Because you have declared a as an array, an expression using that variable's name, on its own, will usually 'decay' to a pointer to the first element of the array (What is array decaying? - but see also the excellent comment added by Eric Postpischil for exceptions). This is similar to using a char[] string where, as you correctly noted, you don't need to use the & operator when passing it as an argument to scanf.
Adding i to this 'base address' of the a array will give the address of (i.e. a pointer to) the 'i'th element of the array.
Here is a decent tutorial on pointer arithmetic in C that you may find useful.
scanf usually takes the address of a variable it's reading into. a is already an address (an array that's decayed to a pointer) and i is simply an offset from that address.
This is equivalent to scanf("%d", &a[i]);; it does the same thing.
The & operator used before a variable in c returns the address of that variable. The base of an array already is the address you want. a+i like you're doing is using pointer arithmetic and changing the base address of the array by i
I have a problem with a void pointer in use with a ternary condition operator.
In case of:
int x = 5;
void * pointer = &x;
printf("x: %d \n", 1 == 1 ? (*((int*)pointer)) : (*((char*)pointer)));
It writes to console the number 5, whitch is correct activity. But when I change in last line char to double:
printf("x: %d \n", 1 == 1 ? (*((int*)pointer)) : (*((double*)pointer)));
Then it writes 0 and I don't know why. I know I can use if-else instead of it but I'm just curious why it is working that way. Could anyone help me?
The result of a ternary expression is the common type of the two branches. In the case of one branch being an int and the other a double then the result will be a double as well.
And you don't print a double value, you attempt to print an int value. Mismatching format specifier and value will lead to undefined behavior.
For more information see e.g. this conditional operator reference.
You should use %lf instead of %d
int x = 5;
void * pointer = &x;
printf("x: %lf \n", 1 == 1 ? (*((int*)pointer)) : (*((char*)pointer)));
This is a C code
int (*a)[3];
a is a pointer to an array of 3 integers
a=(int (*)[3])malloc(sizeof(int)*3);
note the Typecast used here; the number of elements must be specified in the typecast shown. Also, the brackets around the * is necessary.
printf("brrbrrbrr %d %d %d %d\n",&a,a,a+1,a+2);
*(a+0)[0]=40;
*(a+0)[1]=41;
*(a+0)[2]=42;
printf("noobnoob %d %d %d \n",a[0][0],*(a+0)[1],(*(*(a+0)+2)));
The output is:
brrbrrbrr -7077000 29278656 29278668 29278680
noobnoob 40 41 0
I am not getting why the last number is 0 instead of 42?
Indexation has higher precedence than dereferencing a pointer. Your assignments don't do what you want. They are evaluated like:
*((a+0)[0])=40;
*((a+0)[1])=41;
*((a+0)[2])=42;
If you want to keep your syntax, you shall use parenthesis like:
(*(a+0))[0] = 40;
(*(a+0))[1] = 41;
(*(a+0))[2] = 42;
The same applies for printing the second element of the array. *(a+0)[1] shall be (*(a+0))[1].
What you are looking for is
int (*a)[3] = malloc(sizeof(int) *3);
(*a)[0] = 40;
(*a)[1] = 41;
(*a)[2] = 42;
printf("%d %d %d\n",(*a)[0],(*a)[1],(*a)[2]);
a is a pointer to an array of 3 int members. So allocate memory for the pointer and store values as shown above.
If you want the address of where the values are stored then you should do
printf("%p\n",(void*)(a)[0]);
This is not homework, but my last assignment made it clear that I didn't clearly understand pointers when coding C.
Therefore, I tried to type a simple program using pointers just to invert an integer in a function, so I could figure out where the gap in my understanding is.
Apparently, I've arrived at it, but I still cannot figure out what I am doing wrong.
My source code is below.
#include <stdio.h>
float invert(int *num);
void main (void)
{
int num;
float a;
printf("enter an integer \n");
scanf("%i", &num);
printf("Number entered %i \n", num);
a=invert(&num);
printf("This is the invse from main %f \n", a);
}
float invert(int *num) /* function inverts integer */
{
float invse;
printf("num is %i \n\n", *num);
invse = 1/(float)num;
printf("invse is %f \n\n", invse);
return(invse);
}
My thinking was that I used the pointer to direct the computer to use the value stored at the address for num in the function invert(). The pointer appears in the variable declaration. I cast the value stored at that pointer as a float, so I could invert it, and store it in a local variable.
The problem appears to be in the local variable assignment. My compiler returns "invert.c:29:2: error: pointer value used where a floating point value was expected
invse = 1/(float)num;
^
Apparently my code indicates a pointer value for inverse, but I declared it as a float, which I find confusing.
Any help is appreciated. This will save me on completing my larger set of code for my assignment, which I did not post here.
Thanks.
Judging by the printf call inside invert
printf("num is %i \n\n", *num);
you already know that in order to access the value passed to invert for inversion you have to dereference num pointer: *num.
If so, then why aren't you dereferencing num when you perform the inversion itself?
invse = 1/(float)num;
I mean, if you are the one who wrote that printf, you should also realize that the actual inversion should be done as
invse = 1 / (float) *num;
or, alternatively, as
invse = 1.f / *num;
On top of being incorrect your original variant is illegal: you are not allowed to convert pointers to floating-point types in C, which is the reason for the error message.
P.S. From the bigger picture point of view, there's no real reason to pass that the number to invert by pointer. Passing the immediate value would make more sense
float invert(int num)
{
...
In that case you, of course, don't have to dereference anything inside invert.