Values the same but not equal [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
Can somebody explain to me why the following code outputs 0 0. I was under the impression that mathematically a-b == 0 ⇒ a == b
char* V1 = "hello, world!\n";
main(){
F1(V1);
}
F1(A1){
printf("%u %u\n", V1 - A1, V1 == A1);
}

As per the C11 standard, chapter §6.5.6, two pointers can only any only be subtracted if they are from same array object.
When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements. The size of the result is implementation-defined,
and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
If the result is not representable in an object of that type, the behavior is undefined. [...]
That said, you should be using %td for printing a result of type ptrdiff_t, generated from pointer subtraction.
Next, coming to the usage of == operator, it cannot be used to compare the contents of the string (array), it basically compares the pointers themselves (not the content they point to).

As #SouravGhosh pointed out, there is undefined behavior here. Still, it is interesting to understand why the second printed value is sometimes 0 and sometimes 1 (depending on the machine it runs on).
The absence of an explicit type for the input of F means that A1 is implicitly an int. The function call F(V1) thus casts the pointer V1 to an int. On some machines this might be a narrowing conversion, which is why on some machines the comparison V1 == A1 is true while on other machines it is false. Perhaps on some machines both arguments in V1 - A1 are cast to ints (hence the value 0) but in the comparison V1 == A1 (which is ub) tries to cast A1 to a valid address and either fails or casts it to a different address.

Related

Evaluation of expression in printf 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 4 years ago.
Improve this question
Please have a look at below code
#include<stdio.h>
int main(void){
int *ptr,a,b;
a = ptr;
b = ptr + 1;
printf("the value of a,b is %d and %d respectively\n",a,b);
printf("the value of a is %d \n",(ptr));
printf("the value of b is %d \n",(ptr+1));
printf("the value of (ptr+1)-ptr is %d \n",(ptr+1)-ptr);
return 0;
}
Output:
the value of a,b is 0 and 4 respectively
the value of a is 0
the value of b is 4
the value of (ptr+1)-ptr is 1
I am not able to understand why the value of (ptr+1)-ptr is 1 not 4 as 4-0?Is it due to computation optimization?
First of all, what you did is wrong. Pointer arithmetic is valid if both of them point to elements of the same array object or one past the last element of the array object. So it is undefined behavior.
In your case, the subtraction returns how far one is from the other - based on the type of the object pointed to which is int here, and sizeof int being 4 bytes, it returned 1 denoting the 1 int separation. (meaning the same as 4 byte - as can be inferred from the value of a and b).
From §6.5.6¶9 C11 standard (this points out both the points mentioned above)
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements...
And you are printing addresses with %d format specifier. You should use %p format specifier with argument void* casted. And never think of dereferencing these pointers as it would be Undefined Behavior to do so.
I am not able to understand why the value of (ptr+1)-ptr is 1 not 4
No, pointer arithmetic in C happens in units related to the pointed type (not in bytes). Read some C programming book.
So (ptr+1) - ptr is 1, but if you cast each pointer to a char*, e.g. by coding (char*)(ptr-1) - (char*)ptr, you'll get probably 4 (assuming sizeof(int) is 4).
Don't forget to enable all warnings and debug info when compiling: if using GCC, compile with gcc -Wall -Wextra -g, then improve your code to get no warnings at all. Read more about undefined behavior (your code have some) and be scared of it. Use the gdb debugger (or whatever other debugger you can use). Read documentation of every standard function that you are using (and of every external function from some other library), notably of printf.
Later, consider also reading pieces of the C11 standard, e.g. n1570 (a draft which is actually the standard text).
Care about portability (to different computers or compilers).
By definition, compiler optimization should not change the observed behavior and semantics of your program.

C - Why this strange output in printf() [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am confused with the strange output of the following c program.
I am using TurboC and DevC compiler
I will be really pleased if someone will help me out in this.
Program
#include<stdio.h>
#include<conio.h>
int main()
{
clrscr();
printf("%d","hb");
printf("%d","abcde"-"abcde");
//Output is -6 why ?
return 0;
}
Outputs
For TurboC
printf("%d","hb");
//Output is 173 Why ?
// No matter what I write in place of "hb" the output is always 173
printf("%d","abcde"-"abcde");
//Output is -6 why ?
For Dev C
printf("%d","hb");
//Output is 4210688 Why ?
// No matter what I write in place of "hb" the output is always 4210688
printf("%d","abcde"-"abcde");
//Output is 0 why ?
Here, you are passing the memory address of a string literal (a char*):
printf("%d","hb");
However, the specifier which should be used is %p (standing for pointer):
printf("%p\n", "hb"); // The output is in hexadecimal
This will ensure that the same representation size is used by printf when displaying it as for when it was passed to printf. Using %d (int specifier) will result in undefined behaviour when sizeof(int) is not the same as sizeof(char*), and even if the sizes would be equal, using %d may result in having negative values printed (if the most significant bit is set - the sign bit of an int).
As for any memory address, you can't expect it to be the same after the program was recompiled, and even less when using different toolchains.
When the output was the same after changing the "hb" literal with another one, it means that it was allocated at the same address.
Here, two pointers to string literals are subtracted:
printf("%d","abcde"-"abcde");
The result of subtracting two pointers is the number of elements of that type between the addresses pointed by them. But please note, the behaviour is only defined when the pointers point to elements from the same array, or to the first element just after the end of the array.
Again, %d may not be the right specifier to be used. An integer type with its size at least equal to the pointer type may be used, maybe long long int (this should be checked against the specific platform). A subtraction overflow may still happen, or the result may not fit into the cast type, and then the behaviour is again undefined.
char *p1, *p2; // These should be initialized and NOT point to different arrays
printf("%lld\n", (long long int)(p1 - p2));
Also note, C standard library provides stddef.h, which defines the ptrdiff_t type used to store a pointer difference. See this: C: Which character should be used for ptrdiff_t in printf?
Note: As there are two different char arrays, the pointer subtraction is undefined, and therefore information below is only based on assumptions, and presented only because the OP mentioned that this was an exam question.
In our case, as sizeof(char) is 1, it represents exactly the difference in bytes. The difference of -6 is telling that the two identical literals "abcde" were placed in memory first next to the second. The literal is including the string terminator, so it's size is 6.
The other thing that can be deduced from here is that the compiler used by DevC++ was "smarter" (or had other optimization options passed to), to create a single copy in the memory for the "abcde" literal, hence the difference of 0.
A string literal is usually placed in the read-only memory, and the program should not try to modify it, so if the compiler (or the linker in some cases) can "detect" a duplicate, it may reuse the previous literal instead.

what is the difference between array[1][2] and array[1,2]? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
if my two dimensional array is int array[4][5]= {1,2,3,4,5,6,7,8,9,0,11,12,13,14,15,16,17,18,19,20};
when I print a position: printf("%d\n",array[2,0]);. this is printing the address of the value without giving the &. but if I print like this: printf("%d\n",&array[2][0]); it is printing address of the value. As I have given the & it prints the address. but both the address are different. but if I print printf(",:%d\n",array[3,0]); it is printing the same address of array[2,0].
what is the difference between [2][0] and [2,0] accessing the array elements.
Read about comma operator.
array[2][0] is accessing element at third row, first column.
array[2,0] is first executing operation (2,0) (which returns 0) and thus is equivalent to array[0], which returns the first row of array (actually &array[0][0] because it decays to a pointer).
Using array[1,2] is just an example of the comma operator being misused -> 1, 2 evaluates both operands and yields 2 -> you are accessing array[2].
Side note: array is not a good name for an array given std::array.
2, 0 invokes the so-called comma operator which discards the value of all expressions which occur before the last comma and represents the value of the expression on the very right. Hence array[2, 0] is equivalent to array[0], and the array-to-pointer decay yields the address of the element at position 0 in array[0] - that is equivalent to &array[0][0].
array[2,0] doesn't do what you think it should. It only has a single index, which is the expression 2,0. That is, it's equivalent to array[(2,0)]. This expression involves the comma operator, which evaluates each of its operands, and the result of which is the result of the last operand. So in your case, it's equivalent to array[0]. This denotes the first of your "inner" arrays, which when you try to print it, undergoes array-to-pointer conversion and gives you a pointer to the start of that array.
what is the difference between array[1][2] and array[1,2]?
The difference is a pretty big thing.
the first example is an multidimensional array access.
you are accessing the 2nd's elements value of the first array.
The second case is just a 1 dimensional array, where the index is invoked with a comma operator within.
This would be, the cpu has to take the 1, discard all operations amde with it when encoutnering the , and after that taking the 2.
So the second case just accesses the 2nd elements value of a 1 dimensional array.
For better udnerstanding you should read this:
What does the comma operator , do?
Compiler is treating arr[3,0] as arr[0]. This is how comma operator works.
And that's why arr[3,0] and arr[2,0] both are printing the same address because both would resolve to base address i.e arr[0].
For better readability, you can rewrite your array definition as
array[4][5]= {
1,2,3,4,5, //a[0][0~4]
6,7,8,9,10, //a[1][0~4]
11,12,13,14,15, //a[2][0~4]
16,17,18,19,20}; //a[3][0~4]
array[2,0] is a single-level dereferencing using a single index, having a , comma operator.
array[2][0] is a double-level dereferencing, using two indexes.
As per the definition of the , operator,
the comma operator (represented by the token ,) is a binary operator
that evaluates its first operand and discards the result, and then
evaluates the second operand and returns this value (and type).
Now, saying printf("%d\n",array[2,0]);. get evaluated as printf("%d\n",array[0]);
Similarly, printf("%d\n",array[3,0]); also gets evaluated to printf("%d\n",array[0]);
So, they end up producing same result.
On the other hand, printf("%d\n",&array[2][0]);, refers to the address of 1st element in the 3rd row. So it's different.
If you notice the data type, you'll find the difference easily.
array[0] represents the data type of int[5]
array[2][0] represents teh data type of int
Note: To print a pointer, you need to use %p format specifier, not %d.

Am I nuts or did I find an issue with C's design? [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 9 years ago.
Improve this question
Ok, so fgetc() returns an unsigned char cast to int, and EOF at... EOF. What if you're trying to read in a config file to a char array, and your implementation's char is signed? The standard for C99 says that not only is the result implementation-defined to assign an unrepresentable value to a signed variable, but that the implementation can alternatively choose to raise a signal instead!
6.3.1.3 Signed and unsigned integers
When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.49)
Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
Constructs like this are very common:
int c, i = 0;
char arr[1024];
for (; (c = getc(Descriptor)) != EOF && i < sizeof arr - 1; ++i)
{
arr[i] = (char)c;
}
arr[i] = '\0';
It's also implementation-defined to perform the cast if char is signed and the value in c is higher than can be represented.
I find it extremely unlikely that I have found a problem that thousands of programmers have missed over the years, especially with the ubiquitousness of the construct above.
It seems that there is a possibility that non-text code read through this means could cause issues, since some of the bytes could have values that don't fit in a signed char.
I've never seen a modified version of the above construct that actually addresses this put to use.
Have I actually found a flaw relating to the C standard, or noticed something thousands of other programmers have not and failed to implement in their error checking?

C pointer addition and substraction in sect. 6.5.6

I am trying to understand paragraph 8 and 9 of C99 sect 6.5.6 (Additive operators)
Does para 8 mean:
int a [4];
int *p = a;
p --; /* undefined behaviour */
p = a + 4; /* okay */
p --; /* okay */
p += 2; /* undefined behaviour */
p = a;
p += 5 - 5; /* okay */
p = p + 5 - 5; /* undefined behaviour */
For paragraph 9, my understanding had been that ptrdiff_t is always large enough to hold the difference of 2 pointers. But the wording:
'provided the value fits in an object of type ptrdiff_t' seems to suggest this understanding is wrong. Is my understanding wrong or C99 meant something else.
You can find a link to the draft standards here:
http://cboard.cprogramming.com/c-programming/84349-c-draft-standards.html
I don't think your interpretation is correct. In the version I have (n1256) paragraph 9 states:
If the result is not representable in an object of that type, the
behavior is undefined
that is it. If the difference is larger than PRTDIFF_MAX or smaller than PTRDIFF_MIN the behavior is undefined.
Notice that this places the burden on the programmer to check if the difference fits in ptrdiff_t. A "lazy" platform implementation could just choose a narrow type for ptrdiff_t and leave you dealing with that.
Checking for that would not be straight forward since you can't do the substraction without provoking UB. You'd have to use the information that the two pointers point inside (or just beyond) of the same object and where the boundaries of that surrounding object are.
I agree to your understanding of paragraph 8. The standard says
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
It seems that C assumes that there is no pointer overflow inside an array, so you can increment/decrement pointers while you stay inside the array. If the result pointer is leaving the array, an overflow might occur and behaviour is undefined.
Regarding paragraph 9 I guess the standard takes into account that you might for example have an architecture that gives you 32 bit pointers and 32 bit data types, but since the difference of two 32 bit pointers in fact is a sign plus 32 bit (so 33 bits), not every pointer difference might match into a 32 bit ptrdiff_t. With 2 complement architecture this is not a problem, but it might be a problem on other architectures.

Resources