1

The task in my school is as follows:

Create a function which will take as parameter ******str pointer to pointer to pointer to pointer to pointer to pointer of char and sets Follow the white rabbit! to the pointer of char.

void mx_deref_pointer(char ******str);

I am new to C and am extremely confused, even though I've learnt everything I could find about pointers..(

I have come up with the following code:

#include <stdio.h>
#include <stddef.h>

void mx_deref_pointer(char ******str) {
    char *pstr1, **pstr2, ***pstr3, ****pstr4, *****pstr5;
    str = &pstr5;
    pstr5 = &pstr4;
    pstr4 = &pstr3;
    pstr3 = &pstr2;
    pstr2 = &pstr1;
    pstr1 = "Follow the white rabbit!";
    printf("%s", pstr1);
}

int main() {
    char ******pstr6 = NULL;
    mx_deref_pointer(pstr6);
}

It does output Follow the white rabbit, but I don't think it is correct as commenting out most of the function still produces the same result. Also, I don't know how to pass anything other than NULL into the mx_deref_pointer(). Some of the guys who study with me have come up with a different mx_deref_pointer:

void mx_deref_pointer(char ******str) {
    str [0] [0] [0] [0] [0] [0] = "Follow the white rabbit!";
}

It seems to work, however none of them was able to explain to me how it works. I would be extremely grateful if someone could provide a proper piece of code for this and, more importantly, explain what and how it does!

Thank you.

Kali
  • 135
  • 1
  • 1
  • 6
  • `str = &pstr5` won't do anything useful, as C passes all arguments by value. I suggest you do some searching about *emulating pass by reference in C*. – Some programmer dude Jun 06 '19 at 23:54
  • All those pointers belong in `main`, only the most-buried should be sent (by address) to `mx_deref_pointer`, where it is full-dereferenced to set the requested value. – WhozCraig Jun 06 '19 at 23:55
  • Yes, your code is essentially `char *pstr1 = "..."; printf("%s", pstr1);` I would expect that you would be given the code in `main` that initializes `pstr6`. So it's not clear to me whether you've presented the question in its entirety. – user3386109 Jun 06 '19 at 23:56

2 Answers2

3

To comply with the argument of your function (a 6x pointer to char), the address of a 5x pointer to char could be the provided argument from the caller (or the value of a 6x pointer to char, you're choice, so long as they're referring to valid data). Therefore, all of those stacked pointers you have belong in the caller (main), not the function. In short, the function and main should look something like this:

#include <stdio.h>

void mx_deref_pointer(char ******str)
{
    static char msg[] = "Follow the white rabbit!";
    *****str = msg;
}

int main() 
{
    char *ptr1 = NULL;
    char **ptr2 = &ptr1;
    char ***ptr3 = &ptr2;
    char ****ptr4 = &ptr3;
    char *****ptr5 = &ptr4;

    mx_deref_pointer(&ptr5);

    puts(ptr1);
    return 0;
}

Output

Follow the white rabbit!

Note that in an effort to avoid inadvertent undefined behavior, the assignment saves the base address of a non-const buffer containing the string. Technically your compiler must allow this:

void mx_deref_pointer(char ******str)
{
    *****str = "Follow the white rabbit!";
}

But doing so is bad practice since the caller may expect a modifiable string. A string literal is not writable, and stashing it in a char * would allow the code to write to that string, without any warning being issued by the compiler. So it's better to copy the literal into a writable array before returning it.

Regarding how that array-syntax dereference chain works, given some non-void-type pointer p, these are equivalent:

p[n] == *(p+n)

And therefore these are equivalent:

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

But *(p+0) is simply *p. Therefore this:

void mx_deref_pointer(char ******str)
{
    static char msg[] = "Follow the white rabbit!";
    *****str = msg;
}

is equivalent to this:

void mx_deref_pointer(char ******str)
{
    static char msg[] = "Follow the white rabbit!";
    str[0][0][0][0][0] = msg;
}
user3386109
  • 34,287
  • 7
  • 49
  • 68
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • And now for explaining `0[p]`... :-P – Nikos C. Jun 07 '19 at 00:16
  • @NikosC. Already explained here: [With arrays, why is it the case that `a[5]` == `5[a]`?](https://stackoverflow.com/questions/381542/with-arrays-why-is-it-the-case-that-a5-5a) – WhozCraig Jun 07 '19 at 00:24
  • You are the best!! Thank you for taking time to write something so detailed <3 – Kali Jun 07 '19 at 00:33
  • 1
    @Kali Note that `msg` in the function is `static` for a reason. I leave discovering why as a task for you to research. Glad it helped. – WhozCraig Jun 07 '19 at 00:34
  • I was under the impression that technically the compiler was required to accept `char *str = "hello";` as discussed in [this question](https://stackoverflow.com/questions/4493139/are-string-literals-const). – user3386109 Jun 07 '19 at 01:06
  • @user3386109 It's legitimate C99 code, but its a terrible practice. In staying standard compliant, I didn't mean to infer it wouldn't be compilable, but rather the resulting code could allow perfectly modification to an array by simple deref, and in so doing invoke undefined behavior. The code as presented here cannot fall into that folly, as the static array is writable, and therefore does not risk tripping the UB mentioned in 6.4.5-p6. – WhozCraig Jun 07 '19 at 01:16
  • Yes, but saying something is terrible practice is different than saying something violates const-correctness (which it does not), or that the compiler should issue a warning (which it should not). I've edited the answer to be technically correct. Feel free to roll back. – user3386109 Jun 07 '19 at 01:50
2

according to

https://www.programiz.com/c-programming/c-pointers-arrays

x[0] is equivalent to *x.

Aaron
  • 147
  • 2
  • Would I be able to rewrite the str [0] [0] [0] [0] [0] [0] = "Follow the white rabbit!"; with & and * notation? If so, do you know how to do it? – Kali Jun 07 '19 at 00:00
  • 1
    @Kali That would be `******str = "Follow the white rabbit!";` Since `x[0]` is the same as `*x`, then `x[0][0]` is the same as `**x`, and so on. – Nikos C. Jun 07 '19 at 00:20