2

Why do I get a warning when I do this:

char (*arr_ptr)[];
char str[] = "string";

arr_ptr = str;

The warning is:

assignment from incompatible pointer type

But when I change the assignment to:

arr_ptr = &str;

The warning disappears. I thought str, &str, and &str[0] were all the same. So how would str or &str[0] be incompatible?

I think my code is being compiled by GCC since I'm running it on TextMate.

Espresso
  • 4,722
  • 1
  • 24
  • 33
  • 1
    [This question](http://stackoverflow.com/questions/1335786/c-differences-between-pointer-and-array) can probably help you. – netcoder Dec 20 '11 at 07:10
  • possible duplicate of [Why can't I assign an array to pointer directly in C?](http://stackoverflow.com/questions/3504506/why-cant-i-assign-an-array-to-pointer-directly-in-c) – CB Bailey Dec 20 '11 at 07:54
  • 1
    Read section 6 of the [comp.lang.c FAQ](http://c-faq.com). – Keith Thompson Dec 20 '11 at 10:10

3 Answers3

2

In C, str, &str and &str[0] refer to the same address - an array's label is simply a way of referring to the address of the start of a contiguous block of memory. str and &str are obviously of different types, however, &str being of type char (*)[].

If you want arr_ptr to point to "string", you merely have to do:

char *arr_ptr = str;

arr_ptr is simply of type char*, a single level pointer to char.

EDIT: In case I accidentally avoided the question, the reason why assigning &str to char (*arr_ptr)[] removes the error is because of the fact that &str is of type char (*)[], and str is only of type char[] (which can decay to char*).

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
  • Yes, I know. But I still don't see why `str` or `&str[0]` is incompatible. You just changed the definition of `arr_ptr` which avoided the question. – Espresso Dec 20 '11 at 07:24
  • @NSCoder because str is an array of chars, whereas arr_ptr is an array of pointers to chars. – Gnat Dec 20 '11 at 07:29
  • I think it's the other way around. `arr_ptr` is a pointer to array of chars. Wouldn't an array of pointers to char would simply be `*foo[]`? – Espresso Dec 20 '11 at 07:33
  • 3
    Sorry, but **No**: `str != &str`. In the context, `str` is an array of characters, and `&str` is a pointer to an array of characters, and even if the numerical value of the address is the same, the types are different so the equality doesn't apply. – Jonathan Leffler Dec 20 '11 at 07:49
  • @NSCoder - beg your pardon, you are right, getting mixed up between operator and declaration precedence – Gnat Dec 20 '11 at 08:08
  • @JonathanLeffler: I was talking about the addresses, assume they were cast as void*s. I didn't mean `str == &str == &str[0]` to be an actual C statement. Anyway I'll reword it because it does look shonky. – AusCBloke Dec 20 '11 at 08:37
  • @NSCoder: If my answer wasn't clear, the reason the warning goes away is because `&str` is of type `char (*)[]`, the same type as `arr_ptr`. I edited the answer to make that more clear. – AusCBloke Dec 20 '11 at 08:38
1

I thought str, &str and &str[0] were all the same.

No. str is &str[0] - both denote a pointer to the first array element.

&str points to the same place, but is a pointer to the complete array.

The diffrence is the type if you dereference the pointer.

Try

printf("%d %d %d",
       (int)sizeof(*str),
       (int)sizeof(*(&str)),
       (int)sizeof(*(&str[0])));

.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
glglgl
  • 89,107
  • 13
  • 149
  • 217
  • @Keith Thanks for editing. I wasn't aware that `sizeof` yields a `size_t`. Wouldn't it be better to use `%z`, or is that less portable? – glglgl Dec 20 '11 at 11:53
  • `%z` doesn't even exist. `%zu` is the correct format for `size_t`, but it's new in C99, and some C implementations probably don't support it; Microsoft in particular has been less than enthusiastic about supporting C99. Converting to `int` and using `%d` is portable as long as the size doesn't exceed `INT_MAX` (which is at least 32767). You can also cast to `unsigned long` and use `%lu` as long as the size doesn't exceed ULONG_MAX (which is at least 2147483647). – Keith Thompson Dec 20 '11 at 23:01
0

I guess what you were trying was this:

#include <stdio.h>

int main()
{
    char *arr_ptr;
    char str[] = "string";

    arr_ptr = str;

    printf("%s \n", arr_ptr);
    printf("%s \n", str);

    return 0;
}

The following program adds one more dimension for your understanding.

int main()
{
    char **arr_ptr;
    char *str[] = {"string1", "string2", "string3"};
    int i;

    arr_ptr = str;

    for (i=0 ; i<3 ; i++) {
        printf("%s \n", arr_ptr[i]);
        printf("%s \n", str[i]);
    }

    return 0;
}

Hope this helps!

Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
  • The code written in the question - the compiling code - is fine. It is just different (and less usual). You need to know what it does, but it is valid and different from either of your suggestions. – Jonathan Leffler Dec 20 '11 at 07:51
  • I thought by mentioning the (possible) correct way, @NSCoder would be able to figure out his mistake in assigning the incompatible types. Apologies if my approach is not right! – Sangeeth Saravanaraj Dec 20 '11 at 09:35