pointers

A

Anolethron

I'm studying pointers... I understand the meaning of * and & but I don't
understand the use of **.

For instance in

char **order (char **list, int n)

{
char **p = list
char *s; etc...
Can anybody help me, please?
Tnx in advance.
 
U

Ulrich Eckhardt

Anolethron said:
I'm studying pointers... I understand the meaning of * and & but I don't
understand the use of **.

Beware, '*' has many meanings, and two of them in the context of pointers!
For instance in

char **order (char **list, int n)

{
char **p = list
char *s; etc...

If instead of
char *s;
you'd write
char* s;
you would see that it's the same steps in these three here:
char c;
char* d = &c;
char** e = &d;

IOW, a pointer to pointer is just another step of indirection.

Uli
 
K

Keith Thompson

Ulrich Eckhardt said:
Beware, '*' has many meanings, and two of them in the context of pointers!


If instead of
char *s;
you'd write
char* s;

But the point of C's rather odd declaration syntax is that declaration
mirrors use.

The declaration "char *s" means that *s is a char (and therefore s is
a pointer-to-char).

The declaration char **p means that **p is a char (and therefore p is
a pointer-to-pointer-to-char).
 
K

Kenneth Brody

Anolethron said:
I'm studying pointers... I understand the meaning of * and & but I don't
understand the use of **.

For instance in

char **order (char **list, int n)

{
char **p = list
char *s; etc...
Can anybody help me, please?

Simple... "**" is "*" twice. :)

But, seriously:

"char *" is a pointer to "char".
"char **" is a pointer to "char *".
"char ***" is a pointer to "char **".

And so on.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
J

John Bode

Anolethron said:
I'm studying pointers... I understand the meaning of * and & but I don't
understand the use of **.

For instance in

char **order (char **list, int n)

{
char **p = list
char *s; etc...
Can anybody help me, please?
Tnx in advance.

The use of double (or triple, or even more) indirection comes into play
several places.

First, remember that in order to write to a function parameter and have
that value reflected in the calling routine, you must pass a pointer to
that parameter. For example:

void foo(int *x)
{
*x = 1;
}

void bar(void)
{
int x = 0;
foo(&x);
}

Well, the same thing applies to pointer values -- if you want to write
a pointer value to a parameter, you must pass a pointer to that
parameter, to wit:

void openAndTest(FILE **ptr, char *name)
{
**ptr = fopen(name, "r");
...
}

void doStuff(void)
{
FILE *in;

openAndTest(&in, "foo.txt");
...
}

You'll also see multiple indirection when allocating
multiple-dimensioned arrays:

int **alloc2d(size_t row, size_t col)
{
int **arr = NULL;
int i, j;

arr = malloc(sizeof arr[0] * row); // or sizeof *arr
if (arr)
{
for (i = 0; i < row; i++)
{
arr = malloc(sizeof arr[0][0] * col); // or sizeof **arr
if (arr)
{
for (j = 0; j < col; j++)
{
arr[j] = 0;
}
}
}
}
return arr;
}

Hope that helps.
 
A

Alexei A. Frounze

Keith Thompson said:
But the point of C's rather odd declaration syntax is that declaration
mirrors use.

The declaration "char *s" means that *s is a char (and therefore s is
a pointer-to-char).

The declaration char **p means that **p is a char (and therefore p is
a pointer-to-pointer-to-char).

Everything's right, as the correct C goes. But nontheless, everything's
confusing.
By writing char** s or char **s we declare not a character variable but
rather a pointer to character variable, hence the variable type is char** or
char ** and the name of that variable is s but not **s or ** s.
This is another oddity about C that I consider misleading. Especially in a
case like this, declaration of variables:
char* s1, s2;
or
char *s1, s2;
s1 is a variable of type pointer to char. But what's the type of s2? It's
char according to C, although logically the asterisk must have stuck to
char, to the base type from which the actual type (pointer to char) is
derived.
Those who know this odd thing, don't have problems programming it right, but
find this odd.
Those who don't know it yet, will find it *extremely* odd.
If I were to change C, this would be another thing... :)

So, according to C and what the C source code gets compiled to, * is neither
part of type nor part of name.

Alex
 
J

John Bode

Alexei said:
Everything's right, as the correct C goes. But nontheless, everything's
confusing.
By writing char** s or char **s we declare not a character variable but
rather a pointer to character variable, hence the variable type is char** or
char ** and the name of that variable is s but not **s or ** s.
This is another oddity about C that I consider misleading. Especially in a
case like this, declaration of variables:
char* s1, s2;
or
char *s1, s2;
s1 is a variable of type pointer to char. But what's the type of s2? It's
char according to C, although logically the asterisk must have stuck to
char, to the base type from which the actual type (pointer to char) is
derived.
Those who know this odd thing, don't have problems programming it right, but
find this odd.
Those who don't know it yet, will find it *extremely* odd.
If I were to change C, this would be another thing... :)

So, according to C and what the C source code gets compiled to, * is neither
part of type nor part of name.

It *is* part of the type; it's just not part of the type *specifier*.

In the statement

int *foo;

the expression *foo is the declarator, and foo is the symbol being
defined. It is the declarator that introduces additional type
information for any specific symbol. The "int-ness" of foo is given by
the type specifier. The "pointer-ness" of foo is given by the
declarator.

Similarly for types like

int a[10];
double (*f)(int x);
void *(*g(void))[20];

The type of a is "10-element array of int"; the array-ness comes from
the declarator. The type of f is "pointer to function taking one int
parameter and returning double"; the pointer-ness and function-ness
come from the declarator. The type of g is "function taking no
parameters and returning a pointer to an array of pointers to void";
and again, the function-ness, array-ness, and pointer-ness come from
the declarator.

This all falls out of the whole "declaration mimics use" paradigm; if
you want to access a specific element of an integer array, you use the
expression

a

and the type of the result is int. Similarly, when you dereference a
pointer to double, you use the expression

*f

and type of the result is double. That's why you write

int a[10];
double *f;

instead of

int[10] a;
*double f;

for your declarations.
 
A

Alexei A. Frounze

John Bode said:
Alexei A. Frounze wrote: ....

It *is* part of the type; it's just not part of the type *specifier*.

In the statement

int *foo;

the expression *foo is the declarator, and foo is the symbol being
defined. It is the declarator that introduces additional type
information for any specific symbol. The "int-ness" of foo is given by
the type specifier. The "pointer-ness" of foo is given by the
declarator.

Right, the type must be (and effectively is) pointer to int, int*, but the
type is smeared over where it should belong (together with int) and where it
should not (together with name).

....
This all falls out of the whole "declaration mimics use" paradigm; if
you want to access a specific element of an integer array, you use the
expression

a

and the type of the result is int. Similarly, when you dereference a
pointer to double, you use the expression

*f

and type of the result is double. That's why you write

int a[10];
double *f;

instead of

int[10] a;
*double f;

for your declarations.


:) That's why I'd prefer declaring variables 3rd way, more like in Pascal,
where certain things are much more straightforward:

var
a, b : array[0..10] of integer; (* both a and b are arrays of 10 ints *)
p1, p2: ^integer; (* both p1 and p2 are pointers to int *)

This is probably the clearest way to tell the types and separate them from
names/symbols.

Alex
 
B

Barry Schwarz

Everything's right, as the correct C goes. But nontheless, everything's
confusing.
By writing char** s or char **s we declare not a character variable but
rather a pointer to character variable, hence the variable type is char** or

No, you declare a pointer to a pointer to char variable.



<<Remove the del for email>>
 
S

Simon Biber

Alexei said:
:) That's why I'd prefer declaring variables 3rd way, more like in Pascal,
where certain things are much more straightforward:

var
a, b : array[0..10] of integer; (* both a and b are arrays of 10 ints *)
p1, p2: ^integer; (* both p1 and p2 are pointers to int *)

I'd make it more cdecl-like:

a, b: array 10 of int;
p1, p2: pointer to int;

I once thought about making a C preprocessor to translate all
declarations of this form into real C so they can be compiled.

main: function (argc: int,
argv: pointer to pointer to char)
returning int
{
str: pointer to const char = "Hello World\n";
puts(str);
return 0;
}

I'm still not sure what syntax would be best for definitions with
initialisations (possibly multiple initialisations).

a, b: int = 1; // initialises both a and b to 1
a = 2, b = 3: int; // initialises a to 2 and b to 3

Certainly the ability to declare objects of different types in a single
declaration would be lost:

For example, the declaration:
char c, *pc, **ppc, *(*pfrpc)();

Would become:
c: char;
pc: pointer to char;
ppc: pointer to char;
pfrpc: pointer to function returning pointer to char;

Somewhat more typing, but much clearer!
 
A

Alexei A. Frounze

....
Certainly the ability to declare objects of different types in a single
declaration would be lost:

For example, the declaration:
char c, *pc, **ppc, *(*pfrpc)();

Would become:
c: char;
pc: pointer to char;
ppc: pointer to char;
pfrpc: pointer to function returning pointer to char;

Somewhat more typing, but much clearer!

Maybe that (less typing) was the very idea of the C/Unix developers... Just
remember creat() :)

Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,159
Messages
2,570,881
Members
47,418
Latest member
NoellaXku

Latest Threads

Top