I've got some code that outputs bcdefg and I can't understand why.
I google searched but I couldn't find anything.
const char a[]="Abcdefg";
printf("%s",&(sizeof 2[a])[a]);
Why is the output bcdefg, and not Abcdefg?
This code is meant to confuse you, not do anything useful. Don't write code like this. Here is how it is interpreted by the compiler:
2[a] is the same as a[2], which is a value of char type (which value exactly doesn't matter; the compiler even doesn't try to evaluate it)
sizeof 2[a] is the same as sizeof(char), which is equal to 1
&(sizeof 2[a])[a] is a pointer to the character b in the string Abcdef - the one which has the index 1
printf("%s",&(sizeof 2[a])[a]) prints the string, starting at that pointer
Referring to the code excerpt:
printf("%s",&(sizeof 2[a])[a]);
First, most people don't realize it, but the [] operator it actually commutative. a[b] is equivalent to *(a + b), which is equivalent to *(b + a), which is equivalent to b[a].
So 2[a] is equivalent to a[2]. Since a has type const char [], the size of an element is the same as sizeof(char), which is 1.
So we now have:
printf("%s",&1[a]);
Well, 1[a] is equivalent to a[1], or *(a + 1). Applying the address-of operator gives &a[1], or a + 1 (note that &*x is just x).
So we have:
printf("%s", a + 1);
This just prints the string pointed to by a + 1, i.e. everything after the first character of a.
If you just reorder the [] operators without doing anything else, you can see that it's equivalent to:
printf("%s", &a[sizeof a[2]]);
If you break down each segment:
&(sizeof 2[a])[a]
2[a] = a[2]. a[2] = a char element at position 2
sizeof(char) = 1
(1)[a] = a[1]
&(a[1]) = a reference to the 'b' in "bcdefg"
printf() then prints the char array starting with b and ending at the null terminator
Related
So i have this main:
#define NUM 5
int main()
{
int a[NUM]={20,-90,450,-37,87};
int *p;
for (p=a; (char *)p < ((char *)a + sizeof(int) * NUM); ) //same meaning: for (p=a; p<a+NUM;)
*p++ = ++*p < 60 ? *p : 0; //same meaning: *(p++)=++(*p)<60?*p:0;
for(p=a; (char *)p < ((char *)a + sizeof(int) * NUM); )
printf("\n %d ", *p++);
return 0;
}
And i need to find what is the output.
So after try to understand without any idea i run it and this is the output:
21
-89
0
-36
0
So i will glad to explanation how to solve this kind of questions (i have exam soon and this type of questions probably i will see..)
EDIT:
at the beginning i want to understand what the first forstatement doing:
This jump 1 integer ? and what this going inside the block ?
And what is the different between *p++ and ++*p
The question is similar to Why are these constructs (using ++) undefined behavior in C? although not an exact duplicate due to the (subtle) sequence point inside the ?: operator.
There is no predictable output since the program contains undefined behavior.
While the sub-expression ++*p is sequenced in a well-defined way compared to *p because of the internal sequence point of the ?: operator, this is not true for the other combinations of sub-expressions. Most notably, the order of evaluation of the operands to = is not specified:
C11 6.5.15/3:
The evaluations of the operands are unsequenced.
*p++ is not sequenced in relation to ++*p. The order of evaluation of the sub-expressions is unspecified, and since there are multiple unsequenced side-effects on the same variable, the behavior is undefined.
Similarly, *p++ is not sequenced in relation to *p. This also leads to undefined behavior.
Summary: the code is broken and full of bugs. Anything can happen. Whoever gave you the assignment is incompetent.
at the beginning i want to understand what the first for statement doing
This is what one would call code obfuscation... The difficult part is obviously this one:
(char *)p < ((char *)a+sizeof(int)*NUM);
OK, we convert p to a pointer to char, then compare it to another pointer retrieved from array a that points to the first element past a: sizeof(int)*NUM is the size of the array - which we could have gotten much more easily by just having sizeof(a), so (char*)p < (char*)a + sizeof(a)
Be aware that comparing pointers other than with (in-)equality is undefined behaviour if the pointers do not point into the same array or one past the end of the latter (they do, in this example, though).
Typically, one would have this comparison as p < a + sizeof(a)/sizeof(*a) (or sizeof(a)/sizeof(a[0]), if you prefer).
*p++ increments the pointer and dereferences it afterwards, it is short for p = p + 1; *p = .... ++*p, on the other hand first dereferences the pointer and increments the value it is pointing to (note the difference to *++p, yet another variant - can you get it yourself?), i. e. it is equivalent to *p = *p + 1.
The entire line *p++ = ++*p<60 ? *p : 0; then shall do the following:
increment the value of *p
if the result is less than 60, use it, otherwise use 0
assign this to *p
increment p
However, this is undefined behaviour as there is no sequence point in between read and write access of p; you do not know if the left or the right side of the assignment is evaluated first, in the former case we would assign a[i] = ++a[i + 1], in the latter case, a[i] = ++a[i]! You might have gotten different output with another compiler!!!
However, these are only the two most likely outputs – actually, if falling into undefined behaviour, anything might happen, the compiler might just to ignore the piece of code in question, decide not to do anything at all (just exit from main right as the first instruction), the program might crash or it could even switch off the sun...
Be aware that one single location with undefined behaviour results in the whole program itself having undefined behaviour!
Short answer: because of this line
*p++ = ++*p<60 ? *p : 0;
it is impossible to say how the program behaves. When we access *p on the right-hand side, does it use the old or the new value of p, that is, before or after the p++ on the left-hand side gets to it? There is no rule in C to tell us. What there is instead is a rule that says that for this reason the code is undefined.
Unfortunately the person setting the question didn't understand this, thinks that "tricky" code line this is something to make a puzzle about, instead of something to be avoided at all costs.
The only way to really understand this kind of stuff (memory management, pointer behaviour, etc.) is to experiment yourself. Anyway, I smell someone is trying to seem clever fooling students, so I will try to clarify a few things.
int a[NUM]={20,-90,450,-37,87};
int *p;
This structure in memory would be something like:
This creates a vector of five int, so far, so good. The obvious move, given that data, is to run over the elements of a using p. You would do the following:
for(p = a; p < (a + NUM); ++p) {
printf("%d ", *p);
}
However, the first change to notice is that both loops convert the pointers to char. So, they would be:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
printf("%d ", *p);
}
Instead of pointing to a with a pointer to int the code converts pto a pointer to char. Say your machine is a 32bit one. Then an int will probably occupy four bytes. With p being a pointer to int, when you do ++p then you effectively go to the next element in a, since transparently your compiler will jump four bytes. If you convert the int pointer to a char instead, then you cannot add NUM and assume that you are the end of the array anymore: a char is stored in one byte, so ((char *)p) + 5 will point to the second byte in the second element of a, provided it was pointing at the beginning of a before. That is way you have to call sizeof(int) and multiply it by NUM, in order to get the end of the array.
And finally, the infamous *p++ = ++*p<60 ? *p : 0;. This is something unfair to face students with, since as others have already pointed out, the behaviour of that code is undefined. Lets go expression by expression.
++*p means "access p and add 1 to the result. If p is pointing to the first position of a, then the result would be 21. ++*pnot only returns 21, but also stored 21 in memory in the place where you had 20. If you were only to return 21, you would write; *p + 1.
++*p<60 ? *p : 0 means "if the result of permanently adding 1 to the value pointed by p is less than 60, then return that result, otherwise return 0.
*p++ = x means "store the value of x in the memory address pointed by p, and then increment p. That's why you don't find ++p or p++ in the increment part of the for loop.
Now about the whole instruction (*p++ = ++*p<60 ? *p : 0;), it is undefined behaviour (check #Lundin's answer for more details). In summary, the most obvious problem is that you don't know which part (the left or the right one), around the assignment operator, is going to be evaluated first. You don't even know how the subexpressions in the expression at the right of the assignment operator are going to be evaluated (which order).
How could you fix this? It would be actually be very simple:
for (p=a;(char *)p<((char *)a+sizeof(int)*NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
And much more readable. Even better:
for (p = a; p < (a + NUM); ++p) {
*p = (*p + 1) <60 ? (*p + 1) : 0;
}
Hope this helps.
Iam confused with following please describe me how the following works
char ch[10] = "bayant";
char c = "bayant"[2] ;
printf("%c",c);
It produces y but how it is possible?
ch[2]
Is only syntactic sugar for
*(ch + 2)
and since addition is commutative, there is no difference with
*(2 + ch)
That's the same meaning with other array types, of course.
Example:
int array[5] = {1, 2, 3, 4, 5};
// syntactic sugar
printf("%i\n", 3[array]);
printf("%i\n", array[3]);
// for
printf("%i\n", *(array + 3));
printf("%i\n", *(3 + array));
In your example
printf("%c\n",*( 2 + "bayant"));
printf("%c\n", *("bayant" + 2));
I know it can result strange, but that's how C works.
Indexing starts with 0.
"bayant"[0] //b
"bayant"[1] //a
"bayant"[2] //y
"bayant"[3] //a
"bayant"[4] //n
"bayant"[5] //t
Read more about arrays here.
You don't even have to write all that, you can only write, for example:
printf( "%c", "0123456789"[8] );
and you shall see the 8 being printed out. The reason for this can be thought as following:
Whenever your programme encounters anything inside double-quotes, i.e. "0123456789", the computer allocates some piece of memory, long enough to hold this new data, and fills the memory with this new data.
In this case, it will allocate a piece of memory that is 10 + 1 (1 for the string-terminating zero) bytes long, fills them like:
'0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '\0'
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
1st 2nd 3rd 4th 5th 6th . . . . 11th
After that, it grabs the memory location of the very first element, and returns it back to you. In this case, the memory location of the '0' will be returned to you. You may as well call it the pointer, and you may as well call this data-set an array.
Now what would happen if you were to append an array-name (which is the memory location of the first element) with a [0], or prefix it with a *? It would return you the very first element in it, right? "0123456789" evaluates into the memory location of the first element as I said above, so logically, "0123456789"[0] also gives you the first element in it. Same for the remaining elements...
String literals are similar to base address of the string. So if you want index of
"bayant"[2] it is similar to ch[2] which is nothing but 'y'.
This is because string literal is a constant address, so it is similar to accessing the array contents by using pointer *(ch + 2).
In "bayant"[2], "bayant" give its base address, which means it can be treated like a const char * variable, so
"bayant"[0] --> 'b'
"bayant"[1] --> 'a'
......
In another words, "bayant"[2] more or less equals
const char *cp = "bayant";
cp[2];
I known it looks strange, but it is how C syntax works, part of it just strange.
What does the below code do? I'm very confused with its working. Because I thought that the if loop runs till the range of int. But I'm confused when I try to print the value of i. Please help me out with this.
#include<stdio.h>
void main()
{
static int i;
for (;;)
if (i+++”Apple”)
printf(“Banana”);
else
break;
}
It is interpreted as i++ + "Apple". Since i is static and does not have an initializer, i++ yields 0. So the whole expression is 0 + some address or equivalent to if ("Apple").
EDIT
As Jonathan Leffler correctly notes in the comments, what I said above only applies to the first iteration. After that it will keep incrementing i and will keep printing "Banana".
I think at some point, due to overflows (if it doesn't crash) "Apple" + i will yield 0 and the loop will break. Again, I don't really know what a well-meaning compiler should do when one adds a pointer and a large number.
As Eric Postpischil commented, you can only advance the pointer until it points to one-past the allocated space. In your exxample adding 7 will advance the pointer one-past the allocated space ("Apples\0"). Adding more is undefined behavior and technically strange things can happen.
Use int main(void) instead of void main().
The expression i+++"Apple" is parsed as (i++) + "Apple"; the string literal "Apple" is converted from an expression of type "6-element array of char" to "pointer to char", and its value is the address of the first element of the array. The expression i++ evaluates to the current value of i, and as a side effect, the value in i is incremented by 1.
So, we're adding the result of the integer expression i++ to the pointer value resulting from the expression "Apple"; this gives us a new pointer value that's equal or greater than the address of "Apple". So assuming the address of the string literal "Apple" is 0x80123450, then basically we're evaluating the values
0x80123450 + 0
0x80123450 + 1
0x80123450 + 2
...
all of which should evaluate to non-zero, which causes the printf statement to be executed. The question is what happens when i++ results in an integer overflow (the behavior of which is not well defined) or the value of i+++"Apple" results in an overflow for a pointer value. It's not clear that i+++"Apple" will ever result in a 0-valued expression.
This code SHOULD Have been written like this:
char *apple = "Apple";
for(i = 0; apple[i++];)
printf("Banana");
Not only is it clearer than the code posted in the original, it is also clearer to see what it does. But I guess this came from "Look how bizarre we can write things in C". There are lots of things that are possible in C that isn't a great idea.
It is also possible to learn to balance a plate of hot food on your head for the purpose of serving yourself dinner. It doesn't make it a particularly great idea - unless you don't have hands and feet, I suppose... ;)
Edit: Except this is wrong... The equivalent is:
char *apple = "Apple";
for(i = 0; apple+i++ != NULL;)
printf("Banana");
On a 64-bit machine, that will take a while. If it finishes in reasonable time (sending output to /dev/null), I will update. It takes approximitely three minutes on my machine (AMD 3.4GHz Phenom II).
Can anyone please help me understand the following code:
int d = 4;
printf(&d["Hay!Hello %c\n"], &4["BuddyWorld"]); // Hello (some address in char)
printf(&d["Hay!Hello %c\n"], 4["BuddyWorld"]); // Hello y
printf(&d["Hay!Hello %s\n"], 4["BuddyWorld"]); // Segmentation fault
printf(&d["Hay!Hello %s\n"], &4["BuddyWorld"]); // Hello yWorld
printf("d[Hay!Hello %s\n"], &4["BuddyWorld"]);
/* warning: passing argument 1 of 'printf' makes pointer
from integer without a cast */
What is exactly the d[] or &d[] operator? (d is an integer)
Why does &4["BuddyWorld"] and 4[BuddyWorld] yields to different values? ('W' and 'y' respectively)
When you write something like a[i], it gets expanded into *(a + i). (We say a[i] is syntactic sugar for *(a + i)).
Addition is commutative, so "BuddyWorld"[4] = *("BuddyWorld" + 4) = *(4 + "BuddyWorld") = 4["BuddyWorld"], where "BuddyWorld" implicitly stands for its address in memory.
Subscripting in C is weird. a[b] is turned into *(a + b) (the thing at the address obtained by adding b to the pointer a). However, since a + b == b + a, it works the other way around as well (a[b] == b[a]). That's all that's going on. In particular, "HelloWorld" is really a pointer to a character array that stores the characters of the string.
d["Hay!Hello %c\n"] is the same as "Hay!Hello %c\n"[d].
And the & operator gives the address of the pointed content
I am a teaching assistant for a C programming course, and I came across the following line of C code:
char str[] = "My cat's name is Wiggles.";
printf("%c %c %c %c\n", str[5], *(str + 5), *(5 + str), 5[str]);
I never came across the very last argument (5[str]) before, and neither did my professor. I don't think it's mentioned in K&R and C Primer Plus. I found this piece of code in a set of technical interview questions. Does anyone know why C allows you to access an array element that way also? I never heard of an index being outside the set of brackets and the name of an array inside the brackets.
Your help will be greatly appreciated!
Perfectly valid C. From Wikipedia:
Similarly, since the expression a[i] is semantically equivalent to *(a+i), which in turn is equivalent to *(i+a), the expression can also be written as i[a] (although this form is rarely used).
Wacky, but valid.
str[5] directly translates to *(str + 5), and 5[str] directly translates to *(5 + str). Same thing =)
It's basically just the way C works. str[5] is really equivelent to *(str + 5). Since str + 5 and 5 + str are the same, this means that you can also do *(5 + str), or 5[str].
It helps if you don't think of "5" as an index, but rather just that addition in C is commutative.
Similarly, since the expression a[i] is semantically equivalent to *(a+i), which in turn is equivalent to *(i+a), the expression can also be written as i[a] (although this form is rarely used).
http://en.wikipedia.org/wiki/C_syntax#Accessing_elements
Its all same. *ptr or ptr[0] actually means *(ptr+0). So whenever you write *ptr or ptr[0] it goes as *(ptr+0). Let say you want value at ptr[4] so it means you can also write it as *(ptr+4). Now whether you write it as *(ptr+4) or *(4+ptr), it's same. so just for understading if you can write *(ptr+4) as ptr[4] same way *(4+ptr) is same as 4[ptr]. Please go through http://en.wikipedia.org/wiki/C_syntax#Accessing_elements for more details.
if str is an array of type char, then we can access any index say i as below-
str[i]
*(str + i)
char *p = str, then access the index i as p[i] or *(p+i)
It's a funky syntax for sure, but...
str[5] would mean *(str+5)
And
5[str] would mean *(5+str)
Example Code.
#include<stdio.h>
int main(){
int arr[] = {1, 2, 3};
for(int i = 0; i <= 2; i++){
printf("%d\t", i[arr]);
}
return 0;
}
Output:1 2 3