5

In code I would typically use:

#include <stdlib.h>

void dref1(char **blah)
{
    (*blah)[0] = 'a';
    (*blah)[1] = 'z';
    (*blah)[2] = 0x00;
}

/* or */

void dref2(char **blah)
{
    char *p = *blah;

    *p++ = 'w';
    *p++ = 't';
    *p = 0x00;
}


int main(void)
{
    char *buf = malloc(3);

    dref1(&buf);
    puts(buf);
    dref2(&buf);
    puts(buf);
    free(buf);

    return 0;
}

My question is if it is possible / how to dereference and increment pointer directly:

**blah = 'q';       /* OK as (*blah)[0] ? */
(*blah)++;          /* Why not this? */
*((*blah)++) = 'w'; /* ;or. */
...
Runium
  • 1,065
  • 10
  • 21

3 Answers3

14

I don't know what your real intent is, but it seems to me that you need to learn the difference between *p++ and (*p)++ as expressions.

The first expression dereferences the pointer and advances the pointer itself, not the value that is being pointed to.

The second expression dereferences the pointer and modifies the pointed-to value by applying the postfix ++ operator. Whether the pointed-to value is a pointer or simply an integer doesn't matter.

This has to do with the precedence of the unary * operator and the postfix ++ operator. In the absence of parentheses, the ++ operator is applied first and its result is used as the operand of the * operator.

EDIT:

Assuming that blah is of type char **, here is a list of the possible operations and what each one would do:

  • Obviously, blah yields a value of type char **;
  • *blah yields char *;
  • **blah yields char;
  • *(*blah)++ dereferences blah to get a char *, and then the *p++ analogy comes.
  • **blah++ dereferences blah twice to get the pointed-to value and then increments the blah pointer.
  • (**blah)++ dereferences the blah pointer twice, and then the (*p)++ analogy comes.
Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • 1
    Note that `**blah++` is increasing the address of `buf` which is a stack address in this case, assign value to `blah` in next statement may crash the stack. – Elinx Aug 14 '19 at 02:32
3

Yes, we can. Just test a litter. I think you have the idea.

The problem with using blah the way you write, is, that when you come back to main, not only the content of the buffer is changed (correctly as you whant), but the pointer buf itself too. That may be not what you want, and definetivily not what you need to free.

Test:

#include <stdlib.h>

void dref1(char **blah)
{
    (*blah)[0] = 'a';
    (*blah)[1] = 'z';
    (*blah)[2] = 0x00;
}

/* or */

void dref2(char **blah)
{
    char *p = *blah;

    *p++ = 'w';
    *p++ = 't';
    *p = 0x00;
}

void dref3(char **blah)
{
    *(*blah)++ = 'w';
    *(*blah)++ = 't';
    *(*blah) = 0x00;
}

void dref4(char **blah)
{
    **blah = 'q';       /* OK as (*blah)[0] ? */
    (*blah)++;          /* Why not this? */
    *((*blah)++) = 'w'; /* ;or. */

}


int main(void)
{
    char *buf = (char*)malloc(3);
    char *buf1=buf;
    dref1(&buf);
    puts(buf);
    dref2(&buf);
    puts(buf);
    dref3(&buf);
    puts(buf);
    puts(buf1);

    buf=buf1;
    dref4(&buf);
    puts(buf);
    puts(buf1);

    free(buf1);

    return 0;
} 
qPCR4vir
  • 3,521
  • 1
  • 22
  • 32
0

I think there's nothing wrong with the dref1.

(*blah)[0] = *(*blah)+0 = **blah

so you can write (*blah)[0]='a';

There is no point in doing (*blah)++; You are simply incrementing and losing the address returned by malloc.

Bruce
  • 1,647
  • 4
  • 20
  • 22