dont understand with func printf in C - c

This code:
char arr1[20] = "fedcba";
char *ptr;
ptr = &arr1[2];
puts(arr1);
printf("%d\n",*arr1 - *ptr);
printf("%d\n",arr1 - ptr);
I understand that the first printing puts the string.
printf I - what is supposed to print? It says * arr1 - * ptr?
printf II - What is the difference between one and two?

The first prints the difference between 2 chars:
The second prints the difference between 2 pointers.
*arr1 dereferences a char* and returns the first character, which is 'f'.
ptr = &arr1[2]; will make ptr point to "dcba". It takes the address of the third character in arr1. *ptr returns 'd'.
So the first printf returns the difference between characters f and d - which is 2.
The second one is the difference between the two pointers. It's legal since they both point inside the same character array. It's the same as arr1 - &arr[2] which will most likely be -2, since arrays are stored continuously in memory.

printf("%d\n",*arr1 - *ptr);
This prints the result of the first character of arr1 minus the first character of ptr.
Here is clearer version that does the same thing: printf("%d\n",arr1[0] - ptr[0]);
printf("%d\n",arr1 - ptr);
This prints the pointer difference between arr1 and ptr, which is 2.
Essentially the property holds that: (a[x] - a) is equivalent to x

Just add these two lines to your program for better understanding...
printf("\n%d AND %d... %c",arr1, *arr1, *arr1);
printf("\n%d AND %d... %c",ptr, *ptr, ptr[0] ); //ptr[0] == *ptr
Hope this helps...

Related

Displaying pointer substraction

Okay, say I have a sequence "abcdefg" and I do
char* s = strdup("abcdefg");
char* p;
char* q;
p = strchr(s, 'c');// -> cdefg
q = strchr(p, 'd');// -> defg
And I want to display s - p basically abcdefg - cdefg = ab, can I do this using pointer arithmetic?
You can do:
printf("%.*s", (int)(p - s), s);
This prints s with a maximum length of p - s which is the number of characters from s to p.
You cannot. The string is saved as a sequence of letters ending in a zero byte. If you print a pointer as a string, you will tell it to print the sequence up to the zero byte, which is how you get cdefg and defg. There is no sequence of bytes that has 'a', 'b', 0 - you would need to copy that into a new char array. s - p will simply give you 2 (the distance between the two) - there is no amount of pointer arithmetic that will copy a sequence for you.
To get a substring, see Strings in C, how to get subString - copy with strncpy, then place a null terminator.
Okay, if you need to cut p from s, the following code should work:
char s[100]; // Use static mutable array
strcpy(s, "abcdefg"); // init array (ok, ok I dont remember the syntax how to init arrays)
char* p = strchr(s, 'c');// -> cdefg
*p = 0; // cut the found substring off from main string
printf("%s\n", s); // -> ab

Pointer char output explanation

char alpha[] = "abcdefghi";
char ch[80], *pch = &ch[0];
strcpy(ch, alpha);
putchar(*pch++);
putchar((*pch)++);
putchar(*++pch);
putchar(++(*pch));
printf("\n%s", ch);
Why does the putchar function print 'a' 'b' 'c' and 'd' respectively?
Why does printf("\n%s", ch); print acddefghi?
I am really bad with pointer stuff.
OK, I will try to explain this as simply as I can.
When you do: putchar(*pch++) what you say is 'print that character of the address that pch points to and then increment the pch to point to the next address'. Essentially, before the first putchar(), *pch = 'a' and after *pch = 'b'(because pch points now to ch[1]).
Now, in the second putchar() what you say is: 'print the character in the address that pch points to and then increment the value of the CHARACTER, in that address, by 1'. So, instead of doing what you did in the second putchar(), you could replace this line whith these two lines:putchar(*pch); // 'b'
*pch += 1; // see, you increment the value(notice the *), not the pointer.
However, because as I said, it increments the character AFTER the second putchar(), it just prints what it was which is 'b'. So, just to clear, after the second putchar(), ch[0] = 'a'(we did not change anything in this value)
and ch[1] = 'c'(we incremented the value of the character by 1 and 'b' + 1 = 'c'). The rest is unchanged, so ch[2] = 'c', ch[3] = 'd' and so on.. but pch points to ch[1]
Now, in the third putchar(), you do something similar with the first except that you first increment the address that pch points and then print the value of this address.So, you could replace the third putchar() with these two lines:pch++; // increment the pointer by one, it now points to ch[2], which is 'c'(it remained unchanged)
putchar(*pch); // 'c'
So, after the third putchar(), ch[0] = 'a'(remained unchanged), ch[1] = 'c'(changed in the second putchar()), ch[2] = 'c'(remained unchanged)
Finally, in the last putchar(), what you do is similar to the second except that you increment the value of the CHARACTER that pch points to before you print it.
Remember that pch points to ch[2]
So, you could replace the last putchar() with these two lines:
*pch += 1; // 'c' + 1 = 'd'
putchar(*pch); // 'd'
So, after the 4 putchars, ch[0] = 'a'(it remained unchanged), ch[1] = 'c'(changed in the second putchar()), ch[2] = 'd'(changed in the fourth putchar()) and ch[3] = 'd'(it remained unchanged) and the rest of the string remains unchanged, and I think it is now obvious why you get the result you get from printf().
ch is an array of characters. In C an array is just a pointer to the first element in the array. That makes ch a pointer to a char (char *) as well. putchar prints a single character when you pass it a character to print. *pch++ says 'use the character at this address' then increment the address to point at the next char. printf prints the whole string because of the format specifier "\n%s" which tells printf to print the array of characters (a string if you will) which is found at the address ch. Which we know from above is an array of characters. Hope this helps.
Dereferences the pointer and returns back the value 'a', then the pointer is incremented by 1.
putchar(*pch++);
Same as the first explanation above. Returns back 'b'.
putchar((*pch)++);
Increments the pointer then dereference it, the value returned back is 'c'.
putchar(*++pch);
Same as the previous, returns back the value of 'd'.
putchar(++(*pch));
Pointer increments/decrements are based on the type of the variable that is declared.
Since ch is declared an array of characters, printf prints out the entire contents of that said variable.
strcpy(ch, alpha);
Copy the contents of alpha into an array ch, i.e. "abcdefghi"
All "arrays" decay into pointers pointing to the first element of type T.
(They are not really arrays!)
value of address means address location
value of data means the value in that address
Try to think it in this way:
Whatever follows after * is an address.
Eg: *x, here the value of x is an address.
And when you combine * and x i.e. *x, it represents the value at that address.
Whenever you do *p++, the value of p( which is address value) post increments by depending on the data type of the pointer. So, it will point to the next block of address. It won't increment the value of data.
In C, the char pointer points to address of first array and prints the entire array until a null character is received.
Watch lectures on pointer. You will be clear.
*pch++ print current pointer value and increments pointer
(*pch)++ print current pointer value, and increments that value
*++pch It increments pointer and print value of new pointer
++(*pch) It increments value of current pointer and then print that new value
putchar(*pch++); // It prints ch[0], print and increments pointer
putchar((*pch)++); // It prints ch[1], print and increment value;
putchar(*++pch); // It prints ch[2], pointer increments and print
putchar(++(*pch)); // It prints ch[2]+1, increment value and print

Unable to understand the output of the program using printf weirdly

I was working with some of the interview questions when I found this code.
#include<stdio.h>
int main()
{
short int a=5;
printf("%d"+1,a); //does not give compiler error
return 0;
}
It prints the following:
d
I am unable to understand how the printf function works here.
Let's look at the first argument to the printf() call.
"%d" + 1
This points to the same thing as ptr does in the following code.
char *ptr = "%d";
ptr = ptr + 1;
So, what does it mean to increment a pointer? Well, we advance the pointer sizeof(*ptr) * 1 bytes forward.
So, in memory we have:
%d\0
^^
||
|This is where ("%d" + 1) points to.
This is where ("%d") points to.
So, your code is more or less functionally equivalent to doing:
short int a = 5;
printf("d", a);
Which will evaluate and then ignore the extra function argument and print d.
One more thing: You're very close to causing undefined behavior in that code. printf("%d", a) is using the wrong format string. The correct format string for a short int is "%hd".
You can find a full table of format strings here.
"%d" + 1 does pointer arithmetic, the compiler sees it as "d", so
printf("%d"+1,a);
becomes:
printf("d", a);
You can see why it outputs d in your compiler.
As #sharth points out in the comment, the extra argument a here is evaluated and discarded.
This is my answer based off #DCoder 's comment. "%d" is a pointer to the first character of the two character array %d. Incrementing this by one gives a pointer to d. The fact that there is a second argument now does not matter as the result of the expression "%d"+1 is simply the character d. If you try adding 0 your output is 5 as expected. If you try adding 2, there is no output as there is only "" is being passed to printf.
In this case printf("%d"+1,a); = printf("d",a).
You are specifying printf to print from +1 position which is "d", so printf will simply print d on screen.

Character pointer and array

The code snippet is:
char c[]="gate2011";
char *p=c;
printf("%s",p+p[3]-p[1]);
The output is:
2011
Can anyone explain how it came?
-----Thanks in advance-----
Going through each line in turn:
char c[] = "gate2011";
Let's assume that array c is located at memory address 200.
char *p = c;
p is now a pointer to c. It therefore points to memory address 200. The actual content of p is "200", indicating the memory address.
printf("%s", p + p[3] - p[1]);
The value of p is 200 when we treat it like a pointer. However, we can also treat it like an array. p[3] gets the value of the 4th item in the string, which is "e". C stores characters as their ASCII value. The ASCII value of "e" is 101.
Next, we get the value of p[1]. p[1] == "a", which has an ASCII value of 97. Substituting these into the function:
printf("%s", 200 + 101 - 97);
That evaluates to:
printf("%s", 204);
At memory address 204, we have the string "2011". Therefore, the program prints "2011".
I'm not sure why you'd want to do something like this, but anyway, this is what's happening.
p + p[3] - p[1]
Here you are taking a value of one pointer, and adding the value of the char at position 3, and then subtracting the value of the char at position 1. The char values are being implicitly cast to numerical values before doing the addition and subtraction.
If p is location 1000, then the sum 1000 + 101(ASCII for e) - 97(ASCII for a) will be made. Therefore the result is a pointer to location 1004 in memory. The %s in the printf then subsitutes the string that starts at this location, and ends with the special character '\0'. So the string is effectively clipped to "2011" (the first 4 letters are missed because 101 - 97 = 4).
If this still doesn't make sense, I'd suggest you have a good look at how arrays in C work.
What have you expected? Why not?
p[3]-p[1] = 'e'-'a' = 4
p+4 = "2011"

Problem with strchr

I can't get why the following bit of C code doesn't work:
int obtainStringLength(char* str, char c1, char c2) {
char* firstOcurrence = strchr(str, c1);
char* endOcurrence = strchr(str, c2);
return 2+(endOcurrence - firstOcurrence) / sizeof(char*);
}
The idea is to find how many characters are between c1 and c2:
printf("%d\n", obtainStringLength("abc def ghi", 'a', 'i')); //should yield 11
Unfortunately, this is always printing 1. What is the problem? Shouldn't strchr work like C#'s string.IndexOf()?
Division by sizeof(char*)? That's incorrect - the result of subtracting two pointers is a numerical value (ptrdiff_t) corresponding to the number of values, not a pointer or difference of addresses.
There's also the off-by-one error in calculating the length. So that last line should look like:
return 1 + (endOcurrence - firstOcurrence);
Your return statement has several problems, due to not understanding pointer arithmetic.
Pointer subtraction already divides by the element size, and char* was the wrong type anyway.
And you should be adding 1, not 2.
Because each character occupies exactly sizeof (char) bytes; not sizeof (char*) bytes.
And sizeof (char) is, by definition 1, so you can omit it:
return 1 + (endOcurrence - firstOcurrence);
No, strchr() returns a pointer (the address of) the character being sought, or NULL if the character was not found.
That's very different from IndexOf().

Resources