Re: Simple question on Pointers



On Tue, 25 Nov 2008 06:44:03 +0700, "Alan Carre" <alan@xxxxxxxxxxxxxxxxx>
wrote:

"Robby" <Robby@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:C1962AB0-0055-42E0-B8C8-964B666C7462@xxxxxxxxxxxxxxxx
In a similar set up, if I do:
===============
int main()
{
char a[] = "hello world";
char **ap = &a;

return 0;
}
===============

Why does the latter example give the following warning?

c:\dts_visual_c++\misc_c_samples\misc_c_samples\utility.c(10) : warning
C4047: 'initializing' : 'char **' differs in levels of indirection from
'char
(*)[12]'

I know others have responded, but I'm not sure if they've made it perfectly
clear... and re-reading this just now I think I will not be much help
either!

Though you may find it amusing at least to consider the following:

--------------------

It is in fact not entirely incorrect to think of &a as being a char**.

Actually, it is entirely incorrect. The type of &a is char(*)[12], i.e.
"pointer to array of 12 char", which is very different than char**, or
"pointer to pointer to char".

After all, 'a' is a kind-of pointer or address to some characters.

No, it's the name of an array. Thinking of it as a "kind-of-pointer" is
just going to get you into trouble, because it's not a pointer at all.

Just try writing this down:

char a[] = "hello world";
char* pc = a;

No compile warnings. So a is a char* right? WRONG!

The reason it works is that the array "a" undergoes the array-to-pointer
conversion in this context, which produces a pointer to its first element.
The variable pc is initialized to a copy of this pointer.

Well, sticking to 32 bit pointers, we can cast &a to char** (pointer to
char*), and it WILL work (by coincidence really). I say it will, and it does
work, strangely, "provided that we do not attempt to reference 'a' "!

Why? Well, certainly the address of a (&a) is a "pointer type" like any
address, but 'a' itself is not a pointer, it is a "reference".

No, it's not a "reference", which is a term that has a well-defined meaning
in C++. The identifier "a" is simply the name of an array.

What that
means is that 'a' merely "represents", or "is an alias for" a memory address
where a char* is located (with data {"hello world\0"}).

No, there is no char* in "a". The name "a" is an lvalue for a char[12].

But the address
where 'a' is located is does not exist. Ok well, it does exists in a sense,
but it's more like a "dummy label" at best (and moreover, it is never used).
For instance try compiling this:

char a[] = "hello world";
char c = (&a+1)[0][0];

warning C4700: uninitialized local variable 'a' used

What do you mean "uninitialized???" I said a[] = "hello world"; !

That's right, 'a' is not initialized, 'a[]' is initialized though.

I would not say that "a[]" is initialized; I would just say that "a" is
initialized. There's only one thing that can be initialized here, and it's
unusual IME to call it "a[]".

The real problem is that dereferencing &a+1 is undefined. If we assume that
the storage for "a" is at location 0, &a will produce a pointer that points
to location 0, but it has the type char(*)[12]. Therefore, when you say
&a+1, you are referring to memory location 12, and when you dereference
this expression, you're reading past the end of the array "a" into
uninitialized memory. Perhaps this is what the warning is trying to say,
but it's very misleading for it to describe "a" as "uninitialized", because
it certainly is initialized.

So we can certainly write down char c = (&a)[0][0] but only because we're
extracting *(&(a[0])) and:

The first expression doesn't group like the second. Although the end result
is the same, they go through different sequences of evaluations involving
different types and are not equivalent in that sense, but they are both
equivalent in result to the simpler a[0].

a[0], a[1], .... a[12] are all initialized variables (12 variables). 'a',
however, is not.

Again, the array "a" is certainly initialized, and a[i] are not separate
variables; they are all part of "a". BTW, I thought we were talking about a
char[12]. :)

--
Doug Harrison
Visual C++ MVP
.



Relevant Pages

  • Re: Arrays issue
    ... x.c:158: warning: format argument is not a pointer ... size NAMESIZE) of "char". ... encountered a service with extra aliases, ... It happens to be an object of type "pointer to pointer to char" ...
    (comp.lang.c)
  • Re: Problem with va_ macros and arrays of arrays
    ... > the arrays passed to a ... > specific char, somewhat similar to what the standard function ... that with an array of struct, or possibly a pointer to a dynamic array ... > As I'm still a beginner in C without a copy of the standard I ...
    (comp.lang.c)
  • Re: warning: return makes integer from pointer without a cast
    ... That silences the warning, but the warning wasn't the problem. ... strdup returns a result of type char*. ... pointer to integer. ... adding a cast to silence a warning is seldom a good ...
    (comp.lang.c)
  • Re: Having issues trying to copy an array
    ... static char *output ... junk.c:12: warning: initialization discards qualifiers from pointer ...
    (comp.lang.c)
  • Re: Insufficient guarantees for null pointers?
    ... will the compiler know what the bounds are after converting that char * ... to an int *, if it could point to either of two arrays which happen to ... compares equal to the original pointer. ...
    (comp.std.c)