What exactly int/char when we declare double pointer(**q) - c

Lets take 64 bit machine
where pointer is of 8 bytes in 64 bit machine
int *p ; // it is a pointer to integer variable so when i increment p
// i.e., p++ it will increment by 4
char *r; // It is pointer to character .
// So if i increment 'r' it will increment by 1
int **q ; // if i increment q ie.,q++ it will increment 8 bytes
i tried this peace of code if any thing wrong please correct me
int a=10;
int *p;
char *r;
int **q;
p=&a;
q=&p;
printf("p= %p\t r= %p\t q=%p\n",p,r,q);
printf("p(increment)= %p\t r (increment)= %p\tq (increment)= %p ",++p,++r,++q);
output
p= 0x7fff669bb1bc r= 0x7fff669bb2a0 q=0x7fff669bb1a0
p(increment)= 0x7fff669bb1c0 r (increment)= 0x7fff669bb2a1 q (increment)= 0x7fff669bb1a8
what is role of int/char/float in double pointer?

To quote the property of the postfix ++ operator, from C11, chapter §6.5.2.4, Postfix increment and decrement operators, (emphasis mine)
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it). [...]
In case of int *p ;, p is a pointer to type int, hence the increment will be based on sizeof(int)
In case of int **p ;, p is a pointer to type int *, hence the increment will be based on sizeof(int *)

Well, this depend not only on your machine, but also on your implementation. You can figure them out by outputting sizeof p, sizeof r, and sizeof q. Printing sizeof (int *), sizeof (char *), and sizeof (int **) works too.
C programmers traditionally like to know a lot (perhaps more than they
need to) about the underlying machine implementation.
From my perspective, you don't need to know these stuffs, because the compiler will handle this for us (according to the C standard) quite well. Also, most practices making use of these stuffs are essentially undefined behaviors.

In int **p you increment the pointer by the size it points to (i.e. pointer). As the size of pointer is 8, it will increment by 8.
The final type has no role here. It will behave the same like the pointer to pointer to void.

Related

Why does this expression come out to 4 in C?

So this expression comes out to 4:
int a[] = {1,2,3,4,5}, i= 3, b,c,d;
int *p = &i, *q = a;
char *format = "\n%d\n%d\n%d\n%d\n%d";
printf("%ld",(long unsigned)(q+1) - (long unsigned)q);
I have to explain it in my homework and I have no idea why it's coming out to that value. I see (long unsigned) casting q+1, and then we subtract the value of whatever q is pointing at as a long unsigned and I assumed we would be left with 1. Why is this not the case?
Because q is a pointer the expression q+1 employs pointer arithmetic. This means that q+1 points to one element after q, not one byte after q.
The type of q is int *, meaning it points to an int. The size of an int on your platform is most likely 4 bytes, so adding 1 to a int * actually adds 4 to the raw pointer value so that it points to the next int in the array.
Try printing the parts of the expression and it becomes a bit clearer what is going on.
printf("%p\n",(q+1));
printf("%p\n",q);
printf("%ld\n",(long unsigned)(q+1));
printf("%ld\n",(long unsigned)q);
It becomes more clear that q is a pointer pointing to the zeroth element of a, and q+1 is a pointer pointing to the next element of a. Int's are 4 bytes on my machine (and presumably on your machine), so they are four bytes apart. Casting the pointers to unsigned values has no effect on my machine, so printing out the difference between the two gives a value of 4.
0x7fff70c3d1a4
0x7fff70c3d1a0
140735085269412
140735085269408
It's because sizeof(int) is 4.
This is an esoteric corner of C that is usually best avoided.
(If it doesn't make sense yet, add some temporary variables).
BTW, the printf format string is incorrect. But that's not why it's outputting 4.

Using calloc() to create dynamic struct utmp array [duplicate]

char c[] = {'a','b','c'};
int* p = &c[0];
printf("%i\n", sizeof(*p)); //Prints out 4
printf("%i\n", sizeof(*c)); //Prints out 1
I am extremely confused about this section of code. Both p and c represent the address of the array c at the 0th index. But why does sizeof(*p) print out 4? Shouldn't it be 1?
Because p is of type int *, so *p is of type int, which is apparently 4 bytes wide on your implementation.
And use %zu for printing size_t (what sizeof yields) if you don't want your program to invoke undefined behavior.
sizeof(*p) is the size of the int object to which p points.
sizeof(*p) will print size of p which is 4 because of int but c is of char that's why it is 1
In C (not C99) the sizeof operator is strictly a compile time calculation. so when sizeof (*p) [a dereferenced ptr to an integer] is evaluated then the size of int is four.
Note. the (*p) portion of that statement is a "cast" operator. So, sizeof is NOT a function call as in sizeof(xyz), rather it is like sizeof var_name or sizeof (int *).
When your program runs it changes the object pointed to by p, but the value of sizeof (*p) was already computed and hard-coded into your executable load module.
I think your confusion is that you were thinking that C would figure out what data type p was pointing to when your program runs.

Confusing on pointer array

The following is the C code:
char *ptr[100];
printf("%s\n",*ptr++);
My question is: we know that array name is not a variable (Ritchie's book "The C programming language" Page 99), so if we define
int *pa,a[5];
This is legal:
pa = a; pa++;
while this is illegal:
a++;
Here char *ptr[100] defines a char pointer array, so ptr represents the initial address of the array. For the above code, if *ptr++ means *(ptr++), this is illegal because array name cannot be used as a variable, and also it's meaningless because *(ptr++) still gets an address as opposed to %s. However, if *ptr++ means (*ptr)++, it also looks strange... Can anyone help to understand this?
The above is my thinking process, my question is: how can *ptr++ give us a string as the code printf("%s\n",*ptr++); says?
Postfix increment ++ has a higher precedence than dereference *.
Thus, *ptr++ is interpreted as *(ptr++). And as you've correctly figured out, ptr++ isn't allowed if ptr is an array (of anything, values or pointers).
If ptr is a pointer, then *ptr++ will indeed increment the pointer (so it will point to the next value after the operation), and this expression will return the current pointed-to value (before increment of the pointer). This expression is indeed sometimes used, e.g. for copying memory areas, e.g.:
while (...) {
*dest++ = *src++; // Copy the current element, then increment both pointers
}
*ptr++ doesn't necessarily give you a string — it gives you a string if and only if ptr is pointing to a string. And in this case, it's not necessary to post-increment just to get the string — *ptr would be enough. ++ is done for another purpose.
For example, it ptr is a pointer to an "array" of strings (i.e. a pointer to a pointer to achar, i.e. char **ptr), then you could print all the strings like this:
int i;
for (i = 0; i < N; ++i) {
printf("%s\n",*ptr++); // '++' "jumps" to the next string
}
I believe this link should help you.
C/C++ int[] vs int* (pointers vs. array notation). What is the difference?
The array notation has a bounds limit while the pointer notation does not.
If you wanted to access the next in the array with array notation it would look something like a[n++] n being whatever the current index of the array you are at. Where as assigning ptr to a sets ptr to the first index of the array and you can increment a pointer.
*ptr++ is parsed as *(ptr++) - apply the ++ operator to ptr, then dereference the result.
As written, this results in a constraint violation - ptr is an array of pointers to char, and an expression of array type is a non-modifiable lvalue, and as such may not be the target of an assignment or the operand of the ++ and -- operators.
The line
printf("%s\n",*ptr++);
should (indeed, must) result in the compiler issuing a diagnostic on the order of "invalid lvalue in increment" or something along those lines.
No. 1:
void main(void)
{
int i;
char *ptr[3]={"how","are","you"};
for (i=0;i<3;i++)
printf("%s\n",ptr[i]);
}
This prints out correct answer. Good!
No.2:
void main(void)
{
int i;
char *ptr[3];
*ptr[0] = "how";
*ptr[1] = "are";
*ptr[2] = "you";
for (i=0;i<3;i++)
printf("%s\n",ptr[i]);
}
warning: assignment makes integer from pointer without a cast [enabled by default].....Why can't initialize like this?
No.3:
void main(void)
{
int i;
char *ptr[3]={"how","are","you"};
printf("%s\n",*ptr++);
}
error: lvalue required as increment operand....Why can't we use *ptr++?

C Pointer Processing (basics)

I'm still struggling to get comfortable with pointers. Not the concept - I understand memory locations, pointer increments matching variable length, etc - it's the syntax. Here's an example that I think is one reason I get confused/can't get an intuitive grip on it:
int a = 42;
Allocates and puts 42 in an int-sized memory space
int *pa = &a;
Allocates a pointer in memory that points to the address containing the variable "a".
printf("%d \n", *pa);
Prints 42.
Simple/basic. What bothers me is that:
int *pa = &a;
Would seem to indicate that *pa and &a are equal; equal to the memory address of a. But in:
printf("%d \n", *pa);
*pa is the contents of the address pa points to. So *pa appears to be two different things (address or int) depending on context. And makes me concerned that "=" != "=".
Now I'm not trying to complain about/redefine/question the language, I'm just wondering if anyone has any tips that will help me understand this better, make it make more intuitive sense. I assume it makes perfect logical sense if you really know the language; I'm hoping someone can explain it so it seems logical to me, too.
int * is not the same as the * in printf("%d \n", *pa);.
Specifically, int *, the entire thing, is basically a type: A "pointer to an int" type.
In other words, int * is a type.
However, invoking *pa means to dereference the pointer pa. So, * is an operator: the deference operator.
Also, to be pedantic, = is actually the assignment operator.
Three general cases for *:
Pointer type. * will follow a type. Example: int * is the pointer-to-an-int type.
Dereference operator. This is a unary operator, and dereferences a pointer to get the "underlying value" in the memory address.
Multiplication operator. This is a binary operator.
Your confusion seems to be because you initialize and declare the pa pointer at the same time, see this
int a = 42;
int *pa;
pa = &a;
now *pa and &a do not seem to be equal.
In C, there are 3 main uses of the * symbol. It takes place as part of a type, a unary operator, and an arithmetic operator.
The first case, as part of a type is used to initialize a pointer. int* foo means that foo is a pointer to an integer, that means foo holds the address of a pointer.
Ex int* pa = &a, pa == address of a.
The second case, as a unary operator is called the dereferencing operator. Unary is when the * has only a value on it's right. Like this it will act as a dereferencing operator. Dereferencing is expressing the value at a given address.
Ex following from the previous example
pa = &a
if (*pa == 1) Look at what value is at the address p is holding
The third case is trivial, but worth mentioning in how it differs from how it acts as a unary operator. As an arithmetic operator, it needs a value to the left and the right.
Exint x = 5 * 5
TL;DR In int *pa, the * is part of the type, not the variable. It might be more clear to see it as int* pa. When it is not a part of a type, the * is a dereferencing operator, meaning to look at the value present at that address.
It might make more intuitive sense if you used a syntax that explicitly shows pa as a variable with a different type than a. This can be accomplished with simple spacing:
int a = 42;
int* pa = &a;
printf("%d", *pa);
Note that all I've done here is shifted the spacing in the declaration of pa so that the * is attached to its type rather than the variable itself.
Mind you, I do think that the syntax can be construed as confusing - it wouldn't be the first confusing thing about C. Personally I might have preferred the use of something like ! for dereferencing:
int a = 42;
int* pa = &a;
printf ("%d", !pa); /* this is fantasy C */
Of course, then you'd have to come up with something else for logical not...

Need clarification on pointer incrementation

Please help me understand the reason the following code works the way it does:
#include <stdio.h>
int main(){
int a = 10;
void *b = &a;
int *p = b;
printf("%u",*p++);
return 0;
}
I know the output of printf will be 10, but I'm not quite following why *p++ is 10
Here are my steps:
1) void *b = &a; stores the address of a in pointer b
2) int *p = b; pointer p now points to the same data item as pointer b
3) printf("%u",*p++); is where I get confused... the dereference of pointer p is a, which is 10... isn't *p++ basically the same as 10+1 which will be 11?
*p++ is essentially *(p++). It evaluates to the value of p before it is incremented which is the address to a. Then you dereference it which evaluates to the value 10.
The post-increment operator in the expression *p++ applies to the pointer, not the value stored at that location, so the result is never 11, before or after it is evaluated. The expression *p++ means: dereference p (get it's value) then increment p one location. Since p points to an int, incrementing it will move it forward sizeof(int) bytes . The addition does not ever apply to the value that p points to, which is 10.
However, the expression (*p)++ is different. It dereferences p (gets its value) and then increments the value in that memory location. The expression evaluates to the original value. So after executing the statement
int c = (*p)++;
the variable c would equal 10, while a would equal 11.
*p++ is parsed as *(p++). p++ evaluates to p, and then increments p, so the change won't be seen until the next reference to p. So *p is 10, *p++ is 10 (but p now points to &a+1), *++p is undefined behavior (because *(&a+1) is not a valid value), (*p)++ is 10 but changes a to 11, and ++*p (or ++(*p)) is 11 (as is a).
Variable p is a pointer to an int (pointing to a)
The expression *p dereferences the pointer, hence it's like accessing the int a directly.
Operator postfix ++ on pointer p takes precedence over the dereferencing. Therefore *p++ increments the pointer p (to whatever junk is in memory after int a) AFTER the expression is evaluated, so the dereferencing still resolves to a and that's why 10 is printed. But after the statement is run the value of p is changed. So, likely after that statement if you do printf("%u ",*p) you will get an awkward value.
If you do ++*p however, the expression is evaluated as ++ operation on the dereferenced int variable pointed by p. If you want to avoid trouble like this, when not sure, use parenthesis:
(*p)++
++(*p)
And you're making sure you are dereferencing the value and acting on it. Incrementing a pointer value is a very dangerous operation allowed by languages like C and C++, so avoid whenever possible!
Why *p++ is 10 ?
[C11: §6.5.2.4/2]: The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it).
The below statement
printf("%u",*p++);
is equivalent to
printf("%u",*p); /* p points to 'a' and value of `a` is 10. Hence, 10 is printed */
p = p + 1;
p is of type pointer-to-int. Hence, 1 is scaled to sizeof (int).
As a result, p now points to an int at address : p + sizeof (int)
I just want to add my five cents.
For incrementing value indirected via pointer you can use ++*ip or (*ip)++. There is a nice explanation about parentheses in K&R book:
The parentheses are necessary in this last example
(*ip)++; without them, them expression
would increment ip instead of what it points to, because
unary operators like * and ++ associate right to left.
And in your piece of code you got 10 because printf will print original value of variable and only after it wiil be incremented by one due of using of postfix ++ operator.

Resources