Can the pointer dereferencing sign * be called "many"? - c

I saw that pointer to either a single variable or an array in C is declared and printed using the same syntax. So I thought of * to be called many like in regular expression sign * which means many such as x*=xxx....
int a[3] = { 4, 5, 6 };
int b = 3;
int *p, *q; // same syntax for either single variable or array
p = a; // pointer to many int
q = &b; // pointer to an int
printf("%d %d", *p, *q); // same syntax again
So can I call both p and q as pointer to many int for ease of understanding?

No, that's not a good idea. A pointer can only point to a single variable, although that is often the first element of an array. p = a; is the pointer to the first element in the array a, and only to that one. The pointer in itself can't know if there's more valid data following the address it is currently pointing at.
For example, it's not meaningful to write a function like void print_array(int* p) since that function won't know the size of the array, since p only points at the first element. We would rather write something like void print_array(int* p, int size)
Advanced topic (ignore if beginner): A pointer to "many int" would rather be the more exotic feature called "array pointer", such as int (*)[3] = &a;. You can think of this as "a pointer to the whole array" rather than just to the first element.

Well, not really, the types are not interchangeable.
While used as the RHS of assignment (among many other cases), a variable with type array decays to the type of pointer to the first element of the array.note
So,
p = a;
is the same as
p = &(a[0]);
where both the sides are of type pointer to integer (int *).
NOTE:
Quoting C11, chapter §6.3.2.1
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. [...]

Related

How could value of array b[] is filled with another array a[] value from another function?

I found this code in internet.And i am confused from 1 hour.
What i found weird is that array b[] is inside met2() function with local scope. And there is another array a[] which is inside met1() function with it's local scope . But How could value of a[] is transferred to b[] array.
And Most importantly, both function are not returning any values.
This is so confusing. Please Help me out here. I searched online but nobody had asked such questions.
#include <stdio.h>
int main()
{
met2();
return 0;
}
void met1(int a[1])
{
a[0]=199;
}
void met2()
{
int b[1];
met1(b);
printf("%d",b[0]);
}
Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" is converted ("decays") to an expression of type "pointer to T" and the value of the expression is the address of the first element of the array.
When you call
met1(b);
the expression b is converted from type "1-element array of int" to type “pointer to int", and the value of the expression is the address of b[0].
In the function prototype
void met1(int a[1])
the parameter declaration int a[1] is "adjusted" to int *a - it’s actually being declared as a pointer (which is handy, since that’s what the function actually receives).
So whenmet2 calls met1, it’s passing the address of the first element of b. The [] operator can be used on pointers as well as arrays (it’s actually defined in terms of pointer arithmetic - a[i] is interpreted as *(a + i)).
So writing a[0] = 199; in met1 is equivalent to writing b[0] = 199; in met2.
The key here is to understand that whenever we declare an array as parameter of a function, it gets adjusted to a pointer to its first element. C17 6.7.6.3 emphasis mine:
A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation.
This means that void met1(int a[1]) and void met1(int* a) are 100% equivalent. The former gets silently translated to the latter by the compiler.
This is quite confusing because int a[1] looks like an array declaration and one might easily get idea the idea that the array is passed by value. But passing arrays by value isn't possible in C.
In your case, the local array b gets passed to met1 as a pointer to its first element. With a[0] = ... that pointed-at element is changed.

Is there a reason why an array name is not an lvalue?

For example,
int x[10];
int i = 0;
x = &i; //error occurs!
According to C - A Reference Manual, an array name cannot be an lvalue. Thus, x cannot be an lvalue. But, what is the reason the array name cannot be an lvalue? For example, why does an error occur in the third line?
Your reference is incorrect. An array can be an lvalue (but not a modifiable lvalue), and an "array name" (identifier) is always an lvalue.
Take your example:
int x[10];
int i = 0;
x = &i; //error occurs!
Apply C11 6.5.1, paragraph 2:
An identifier is a primary expression, provided it has been declared
as designating an object (in which case it is an lvalue) ...
We see that x is a primary expression and is an lvalue, because it has previously been declared as designating an array object.
However, the C language rules state that an array expression in various contexts, including the left-hand-side of an assignment expression, are converted to a pointer which points at the first element of the array and is not an lvalue, even if the array was. Specifically:
Except when it is the operand of the sizeof operator, the _Alignof operator, or the
unary & operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue. If the array object has
register storage class, the behavior is undefined.
(C11 6.3.2.1 paragraph 3).
The pointer which is the result of the conversion specified above is not an lvalue because an lvalue designates an object, and there is no suitable object holding the pointer value; the array object holds the elements of the array, not a pointer to those elements.
The example you use in your question implies that you understand that an array expression decays (is converted to) a pointer value, but I think you are failing to recognize that after the conversion, the pointer value and the array are two different things. The pointer is not an lvalue; the array might be (and in your example, it is). Whether or not arrays are lvalues in fact has no bearing on your example; it is the pointer value that you are trying to assign to.
If you were to ask instead: Why do arrays decay to pointers when they are on the left-hand-side of an assignment operator? - then I suspect that there is no particularly good answer. C just doesn't allow assignment to arrays, historically.
Array names are non-modifiable lvalues in C.:)
Arrays are named extents of memory where their elements are placed. So you may not substitute one extent of memory for another extent of memory. Each extent of memory initially allocated for an array declaration has its own unique name. Each array name is bounded with its own extent of memory.
An array is an lvalue, however it is a non-modifiable lvalue.
It most likely has to do with compatibility of types. For example, you can do this:
struct ss {
char c[10];
};
...
struct ss s1 = { { "hello" } };
struct ss s2 = s1;
But not this:
char s1[10] = "hello";
char s2[10] = s1;
It's true that array names yield pointer values in many contexts. But so does the & operator, and you don't expect that to be assignable.
int i = 42;
int *j = malloc(sizeof *j);
&i = j; /* obviously wrong */
int a[] = {1,2,3};
&a[0] = j; /* also obviously wrong */
a = j; /* same as the previous line! */
So when learning the relationship between arrays and pointers, remember that a is usually the same as &a[0] and then you won't think lvalue-ness is an exception to the rule - it follows the rule perfectly.

C pointer to pointer

Does
int **p
and
int *p[1]
mean the same thing? as both can be passed to functions allowing the change the pointer object, also both can be accessed via p[0], *p ?
Update, thanks for your help, tough Memory management seems different. does the access mechanism remain the same
*eg: p[0] becomes *(p+0) & *p (both pointing to something)
Thanks
Not quite.
int **p;
declares a pointer p, which will be used to point at objects of type int *, ie, pointers to int. It doesn't allocate any storage, or point p at anything in particular yet.
int *p[1];
declares an array p of one pointer to int: p's type can decay to int ** when it's passed around, but unlike the first statement, p here has an initial value and some storage is set aside.
Re. the edited question on access syntax: yes, *p == p[0] == *(p+0) for all pointers and arrays.
Re. the comment asking about sizeof: it deals properly with arrays where it can see the declaration, so it gives the total storage size.
void foo()
{
int **ptr;
int *array[10];
sizeof(ptr); // just the size of the pointer
sizeof(array); // 10 * sizeof(int *)
// popular idiom for getting count of elements in array:
sizeof(array)/sizeof(array[0]);
}
// this would always discard the array size,
// because the argument always decays to a pointer
size_t my_sizeof(int *p) { return sizeof(p); }
To simplify things, you could factor out one level of pointers since it's not relevant to the question.
The question then becomes: what's the difference between T* t and T t[1], where T is some type.
There are several differences, but the most obvious one has to do with memory management: the latter allocates memory for a single value of type T, whereas the the former does not (but it does allocate memory for the pointer).
They are not the same thing, although in many cases they can appear to behave the same way.
To make the discussion below flow better, I'm going to take the liberty of renaming your variables:
int **pp; // pointer to pointer
int *ap[1]; // array of pointer
If an expression of type "N-element array of T" appears in most contexts, it will be converted to an expression of type "pointer to T" whose value is the address of the first element in the array (the exceptions to this rule are when the array expression is an operand of either the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration).
So, suppose you write something like
foo(ap);
The expression ap has type "1-element array of pointer to int", but by the rule above it will be converted to an expression of type "pointer to pointer to int"; thus, the function foo will receive an argument of type int **, not int *[1].
On the other side of the equation, subscripting is defined in terms of pointer arithmetic: E1[E2] is defined as *(E1 + E2) where one of the expressions is a pointer value and the other is an integral value. Thus you can use a subscript operator on pp as though it were an array. This is why we can treat dynamically-allocated buffers as though they were regular arrays:
pp = malloc(sizeof *pp * N); // allocate N pointers to int (type of *pp == int *)
if (pp)
{
size_t i;
for (i = 0; i < N; i++)
pp[i] = ...; // set pp[i] to point to some int value
}
Now for some major differences. First of all, array expressions may not be the target of an assignment; for example, you can't write something like
ap = some_new_pointer_value();
As mentioned above, array expressions will not be converted to pointer types if they are the operands of either the sizeof or unary & operators. Thus, sizeof ap tells you the number of bytes required to store a 1-element array of type int *, not a pointer to a pointer to int. Similarly, the expression &ap has type int *(*)[1] (pointer to 1-element array of pointer to int), rather than int *** (which would be the case for &pp).
No, they are not the same.
int **p is a pointer to a pointer to int.
int *p[1] is an array (of length 1) of pointers to int.
They are not same:
int **p
Is a pointer which points to another pointer whose type is int *
while,
int *p[1];
Is an array of size 1 to the type int *
They are different.
int **p
means a pointer to a pointer to an int.
int *p[1]
means an array containing one element, with that element being a pointer to an int.
The second form can be treated the same as the first in some situations, e.g. by passing it to a function.

How to understand the pointer star * in C?

I'm struggling with the pointer sign *, I find it very confusing in how it's used in both declarations and expressions.
For example:
int *i; // i is a pointer to an int
But what is the logic behind the syntax? What does the * just before the i mean? Let's take the following example. Please correct me where I'm wrong:
char **s;
char *(*s); // added parentheses to highlight precedence
And this is where I lose track. The *s between the parantheses means: s is a pointer? But a pointer to what? And what does the * outside the parentheses mean: a pointer to what s is pointing?
So the meaning of this is: The pointer pointing to what s is pointing is a pointer to a char?
I'm at a loss. Is the * sign interpreted differently in declarations and expressions? If so, how is it interpreted differently? Where am I going wrong?
Take it this way:
int *i means the value to which i points is an integer.
char **p means that p is a pointer which is itself a pointer to a char.
int i; //i is an int.
int *i; //i is a pointer to an int
int **i;//i is a pointer to a pointer to an int.
Is the * sign interpreted differently in declarations and expressions?
Yes. They're completely different. in a declaration * is used to declare pointers. In an expression unary * is used to dereference a pointer (or as the binary multiplication operator)
Some examples:
int i = 10; //i is an int, it has allocated storage to store an int.
int *k; // k is an uninitialized pointer to an int.
//It does not store an int, but a pointer to one.
k = &i; // make k point to i. We take the address of i and store it in k
int j = *k; //here we dereference the k pointer to get at the int value it points
//to. As it points to i, *k will get the value 10 and store it in j
The rule of declaration in c is, you declare it the way you use it.
char *p means you need *p to get the char,
char **p means you need **p to get the char.
Declarations in C are expression-centric, meaning that the form of the declaration should match the form of the expression in executable code.
For example, suppose we have a pointer to an integer named p. We want to access the integer value pointed to by p, so we dereference the pointer, like so:
x = *p;
The type of the expression *p is int; therefore, the declaration of p takes the form
int *p;
In this declaration, int is the type specifier, and *p is the declarator. The declarator introduces the name of the object being declared (p), along with additional type information not provided by the type specifier. In this case, the additional type information is that p is a pointer type. The declaration can be read as either "p is of type pointer to int" or "p is a pointer to type int". I prefer to use the second form, others prefer the first.
It's an accident of C and C++ syntax that you can write that declaration as either int *p; or int* p;. In both cases, it's parsed as int (*p); -- in other words, the * is always associated with the variable name, not the type specifier.
Now suppose we have an array of pointers to int, and we want to access the value pointed to by the i'th element of the array. We subscript into the array and dereference the result, like so:
x = *ap[i]; // parsed as *(ap[i]), since subscript has higher precedence
// than dereference.
Again, the type of the expression *ap[i] is int, so the declaration of ap is
int *ap[N];
where the declarator *ap[N] signifies that ap is an array of pointers to int.
And just to drive the point home, now suppose we have a pointer to a pointer to int and want to access that value. Again, we deference the pointer, then we dereference that result to get at the integer value:
x = **pp; // *pp deferences pp, then **pp dereferences the result of *pp
Since the type of the expression **pp is int, the declaration is
int **pp;
The declarator **pp indicates that pp is a pointer to another pointer to an int.
Double indirection shows up a lot, typically when you want to modify a pointer value you're passing to a function, such as:
void openAndInit(FILE **p)
{
*p = fopen("AFile.txt", "r");
// do other stuff
}
int main(void)
{
FILE *f = NULL;
...
openAndInit(&f);
...
}
In this case, we want the function to update the value of f; in order to do that, we must pass a pointer to f. Since f is already a pointer type (FILE *), that means we are passing a pointer to a FILE *, hence the declaration of p as FILE **p. Remember that the expression *p in openAndInit refers to the same object that the expression f in main does.
In both declarations and expressions, both [] and () have higher precedence than unary *. For example, *ap[i] is interpreted as *(ap[i]); the expression ap[i] is a pointer type, and the * dereferences that pointer. Thus ap is an array of pointers. If you want to declare a pointer to an array, you must explicitly group the * with the array name, like so:
int (*pa)[N]; // pa is a pointer to an N-element array of int
and when you want to access a value in the array, you must deference pa before applying the subscript:
x = (*pa)[i];
Similarly with functions:
int *f(); // f is a function that returns a pointer to int
...
x = *f(); // we must dereference the result of f() to get the int value
int (*f)(); // f is a pointer to a function that returns an int
...
x = (*f)(); // we must dereference f and execute the result to get the int value
My favorite method to parse complicated declarators is the clockwise-spiral rule.
Basically you start from the identifier and follow a clockwise spiral. See the link to learn exactly how it's used.
Two things the article doesn't mention:
1- You should separate the type specifier (int, char, etc.) from the declarator, parse the declarator and then add the type specifier.
2- If you encounter square brackets which denote an array, make sure you read the following square brackets (if there are any) as well.
int * i means i is a pointer to int (read backwards, read * as pointer).
char **p and char *(*p) both mean a pointer to a pointer to char.
Here's some other examples
int* a[3] // a is an array of 3 pointers to int
int (*a)[3] //a is a pointer to an array of 3 ints
You have the answer in your questions.
Indeed a double star is used to indicate pointer to pointer.
The * in declaration means that the variable is a pointer to some other variable / constant. meaning it can hold the address of variable of the type. for example: char *c; means that c can hold the address to some char, while int *b means b can hold the address of some int, the type of the reference is important, since in pointers arithmetic, pointer + 1 is actually pointer + (1 * sizeof(*pointer)).
The * in expression means "the value stored in the address" so if c is a pointer to some char, then *c is the specific char.
char *(*s); meaning that s is a pointer to a pointer to char, so s doesn't hold the address of a char, but the address of variable that hold the address of a char.
here is a bit of information
variable pointer
declaring &a p
reading/ a *p
processing
Declaring &a means it points to *i. After all it is a pointer to *int. An integer is to point *i. But if consider j = *k is the pointer to the pointer this, means &k will be the value of k and k will have pointer to *int.

In C, are arrays pointers or used as pointers?

My understanding was that arrays were simply constant pointers to a sequence of values, and when you declared an array in C, you were declaring a pointer and allocating space for the sequence it points to.
But this confuses me: the following code:
char y[20];
char *z = y;
printf("y size is %lu\n", sizeof(y));
printf("y is %p\n", y);
printf("z size is %lu\n", sizeof(z));
printf("z is %p\n", z);
when compiled with Apple GCC gives the following result:
y size is 20
y is 0x7fff5fbff930
z size is 8
z is 0x7fff5fbff930
(my machine is 64 bit, pointers are 8 bytes long).
If 'y' is a constant pointer, why does it have a size of 20, like the sequence of values it points to? Is the variable name 'y' replaced by a memory address during compilation time whenever it is appropiate? Are arrays, then, some sort of syntactic sugar in C that is just translated to pointer stuff when compiled?
Here's the exact language from the C standard (n1256):
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
The important thing to remember here is that there is a difference between an object (in C terms, meaning something that takes up memory) and the expression used to refer to that object.
When you declare an array such as
int a[10];
the object designated by the expression a is an array (i.e., a contiguous block of memory large enough to hold 10 int values), and the type of the expression a is "10-element array of int", or int [10]. If the expression a appears in a context other than as the operand of the sizeof or & operators, then its type is implicitly converted to int *, and its value is the address of the first element.
In the case of the sizeof operator, if the operand is an expression of type T [N], then the result is the number of bytes in the array object, not in a pointer to that object: N * sizeof T.
In the case of the & operator, the value is the address of the array, which is the same as the address of the first element of the array, but the type of the expression is different: given the declaration T a[N];, the type of the expression &a is T (*)[N], or pointer to N-element array of T. The value is the same as a or &a[0] (the address of the array is the same as the address of the first element in the array), but the difference in types matters. For example, given the code
int a[10];
int *p = a;
int (*ap)[10] = &a;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
p++;
ap++;
printf("p = %p, ap = %p\n", (void *) p, (void *) ap);
you'll see output on the order of
p = 0xbff11e58, ap = 0xbff11e58
p = 0xbff11e5c, ap = 0xbff11e80
IOW, advancing p adds sizeof int (4) to the original value, whereas advancing ap adds 10 * sizeof int (40).
More standard language:
6.5.2.1 Array subscripting
Constraints
1 One of the expressions shall have type ‘‘pointer to object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.
Semantics
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).
Thus, when you subscript an array expression, what happens under the hood is that the offset from the address of the first element in the array is computed and the result is dereferenced. The expression
a[i] = 10;
is equivalent to
*((a)+(i)) = 10;
which is equivalent to
*((i)+(a)) = 10;
which is equivalent to
i[a] = 10;
Yes, array subscripting in C is commutative; for the love of God, never do this in production code.
Since array subscripting is defined in terms of pointer operations, you can apply the subscript operator to expressions of pointer type as well as array type:
int *p = malloc(sizeof *p * 10);
int i;
for (i = 0; i < 10; i++)
p[i] = some_initial_value();
Here's a handy table to remember some of these concepts:
Declaration: T a[N];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N] T * Address of the first element in a;
identical to writing &a[0]
&a T (*)[N] Address of the array; value is the same
as above, but the type is different
sizeof a size_t Number of bytes contained in the array
object (N * sizeof T)
*a T Value at a[0]
a[i] T Value at a[i]
&a[i] T * Address of a[i]
Declaration: T a[N][M];
Expression Type Converts to Value
---------- ---- ------------ -----
a T [N][M] T (*)[M] Address of the first subarray (&a[0])
&a T (*)[N][M] Address of the array (same value as
above, but different type)
sizeof a size_t Number of bytes contained in the
array object (N * M * sizeof T)
*a T [M] T * Value of a[0], which is the address
of the first element of the first subarray
(same as &a[0][0])
a[i] T [M] T * Value of a[i], which is the address
of the first element of the i'th subarray
&a[i] T (*)[M] Address of the i-th subarray; same value as
above, but different type
sizeof a[i] size_t Number of bytes contained in the i'th subarray
object (M * sizeof T)
*a[i] T Value of the first element of the i'th
subarray (a[i][0])
a[i][j] T Value at a[i][j]
&a[i][j] T * Address of a[i][j]
Declaration: T a[N][M][O];
Expression Type Converts to
---------- ---- -----------
a T [N][M][O] T (*)[M][O]
&a T (*)[N][M][O]
*a T [M][O] T (*)[O]
a[i] T [M][O] T (*)[O]
&a[i] T (*)[M][O]
*a[i] T [O] T *
a[i][j] T [O] T *
&a[i][j] T (*)[O]
*a[i][j] T
a[i][j][k] T
From here, the pattern for higher-dimensional arrays should be clear.
So, in summary: arrays are not pointers. In most contexts, array expressions are converted to pointer types.
Arrays are not pointers, though in most expressions an array name evaluates to a pointer to the first element of the array. So it is very, very easy to use an array name as a pointer. You will often see the term 'decay' used to describe this, as in "the array decayed to a pointer".
One exception is as the operand to the sizeof operator, where the result is the size of the array (in bytes, not elements).
A couple additional of issues related to this:
An array parameter to a function is a fiction - the compiler really passes a plain pointer (this doesn't apply to reference-to-array parameters in C++), so you cannot determine the actual size of an array passed to a function - you must pass that information some other way (maybe using an explicit additional parameter, or using a sentinel element - like C strings do)
Also, a common idiom to get the number of elements in an array is to use a macro like:
#define ARRAY_SIZE(arr) ((sizeof(arr))/sizeof(arr[0]))
This has the problem of accepting either an array name, where it will work, or a pointer, where it will give a nonsense result without warning from the compiler. There exist safer versions of the macro (particularly for C++) that will generate a warning or error when it's used with a pointer instead of an array. See the following SO items:
C++ version
a better (though still not perfectly safe) C version
Note: C99 VLAs (variable length arrays) might not follow all of these rules (in particular, they can be passed as parameters with the array size known by the called function). I have little experience with VLAs, and as far as I know they're not widely used. However, I do want to point out that the above discussion might apply differently to VLAs.
sizeof is evaluated at compile-time, and the compiler knows whether the operand is an array or a pointer. For arrays it gives the number of bytes occupied by the array. Your array is a char[] (and sizeof(char) is 1), thus sizeof happens to give you the number of elements. To get the number of elements in the general case, a common idiom is (here for int):
int y[20];
printf("number of elements in y is %lu\n", sizeof(y) / sizeof(int));
For pointers sizeof gives the number of bytes occupied by the raw pointer type.
In
char hello[] = "hello there"
int i;
and
char* hello = "hello there";
int i;
In the first instance (discounting alignment) 12 bytes will be stored for hello with the allocated space initialised to hello there while in the second hello there is stored elsewhere (possibly static space) and hello is initialised to point to the given string.
hello[2] as well as *(hello + 2) will return 'e' in both instances however.
In addition to what the others said, perhaps this article helps: http://en.wikipedia.org/wiki/C_%28programming_language%29#Array-pointer_interchangeability
If 'y' is a constant pointer, why does it have a size of 20, like the sequence of values it points to?
Because z is the address of the variable, and will always return 8 for your machine. You need to use the dereference pointer (&) in order to get the contents of a variable.
EDIT: A good distinction between the two: http://www.cs.cf.ac.uk/Dave/C/node10.html

Resources