2

Look at the strange line from function f:

typedef char thing[1];

void f(thing t){
    thing *p;

    /* Strange line. Changing t to  &t is wrong. 
       C++ require a (thing *) cast.
     */
    p = t;

    *(*p) = 'C';
}

int main(int argc, char* argv[])
{
    thing g;
    thing *h;

    /* Works as expected. */
    h = &g;  

    g[0] = 'A';
    *(*h) = 'B';
    f(g);

    /* g[0] is now  'C' */

    return 0;
}

Changing f to

void f(thing t){
    char **p; 
    p = &t; /* note the & */
    *(*p) = 'C';
}

also works.

I was expecting p=&t to be the right instruction, not p=t. After all t is a thing and &t must be a thing*.

What happened in that strange line?

1

4 Answers 4

4

When passing an array as a parameter, it decays to a pointer. So f actually gets a char *.
Then you try to dereference it twice - you treat it as a pointer to another pointer, which points to char. This can't work, no matter how you do it.
If you don't cast it, C++ (and C, if you enable warnings) tells you something's wrong. If you do cast, you actually tell the compiler to ignore the error. But it's still wrong.

Sign up to request clarification or add additional context in comments.

3 Comments

where are the casts you're talking about?
@Cheersandhth.-Alf, there's a comment about C++ requiring a cast.
oh, you're talking about the cast and address operator that presumably was there before the comment was added. then i would suggest writing "tried" (past tense, original code) rather than "try" (present tense, current code). anyway, would be nice if you could make more clear what exactly you're talking about, since it doesn't refer to the current code as given by the OP.
2

No, t is not a thing.

As a formal argument an array type (but not a reference to array) decays to a pointer to the first element, and a function type decays to a pointer to function.

So in the function you're not taking the address of an array, but the address of a pointer variable, which yields a pointer to a pointer.

Comments

1

Just an alternative solution:

You can prevent the array-to-pointer decay by passing the array by reference. This should work as you want:

void f(thing& t){
    thing *p;

    p=&t;

    *(*p)='C';
}

1 Comment

@user1478370, If it has to work in C, and can't use C++ features, I wouldn't recommend tagging it as C++.
0

Let's literally take this line by line and hope anything you don't understand becomes crystal clear:

void f(thing t){

Here, you're not passing the array by reference, so it decays into a pointer to the first element of the array (t is a char *).

thing *p;

Here, p is a pointer to an array of 1 character, so char (*p) [1].

p=t;

Now you're trying to assign a pointer to a character to a pointer to an array. The types simply don't match (I get something like invalid conversion from char * to char (*)[1]).

*(*p)='C';

This simply dereferences p to get the actual array, which then decays to a pointer to the first element to be dereferenced, effectively giving you the first element.


In main:

thing g;
thing *h

Now you're not dealing with it being passed to a function. g is a char [1] and h is a char (*)[1].

h=&g;  

h is a pointer to an array, g is an array. This makes perfect sense.

g[0]='A';

g is an array; this is normal.

*(*h)='B';

Here you're doing the same thing as in f().


In the modified function:
First of all, remember t is a pointer to the fist element (char *)

char * *p; 

p is a pointer to char *.

p=&t; /* note the & */

You're assigning the address of a char * to a pointer to char *. Perfectly normal.

*(*p)='C';

*p dereferences p to get the char * (t). Another dereference gives you what's pointed to by t, which is the first element of the array.

I hope that clears up any confusion.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.