# Peeter Joot's (OLD) Blog.

• ## Archives

 Adam C Scott on avoiding gdb signal noise… Ken on Scotiabank iTrade RESP …… Alan Ball on Oops. Fixing a drill hole in P… Peeter Joot's B… on Stokes theorem in Geometric… Exploring Stokes The… on Stokes theorem in Geometric…

• 293,785

## Address of an array base. What was the C language designer smoking?

Posted by peeterjoot on June 8, 2010

I regularly see code that grabs the address of the first element in an array in different ways. Some made up examples:

```void bar( char * ) ;

void foo
{
char x[3] ;

bar( x ) ;
bar ( &x ) ;
bar( &x[0] ) ;
bar( (&x[0]) ) ;
}
```

Sometimes these get really complex looking when the array element is in some nested structure and the coder in question is so unsure about how to get the first element address that lots of extra braces are tossed in.

It’s worthwhile demonstrating to oneself that these are all identical. Something like the following does the job:

```#include <stdio.h>

int main()
{
char x[3] ;

printf("%p %p %p\n", x, &x, &x[0] ) ;

return 0 ;
}
```

What I have to wonder about something like this is why would the language allow both x and &x as equivalent syntax? Is it so counterintuitive to have x == &x, but this is actually true in this case! Even though I’ve seen it time and time again, the &x syntax seems to be much less common than just x or &x[0], and it throws me off when I see it.

I get the rough impression, at least from our code, that the &x[0] form is generally preferred. I’d infer from this that is it not obvious to many that just plain x is the array base address, and thus the address of the first element.

1. ### Sam Kendallsaid

Not quite. If x is an array, then &x is the address of the entire array, not of the first element. In your example, the compiler should flag bar(&x) as a type mismatch.

• ### peeterjootsaid

But that doesn’t change the fact that when one is allowed to use &x, it provides both the address of the array and the first element, and there is not any functional difference. For example:

```#include <stdio.h>

void foo(char * x)
{
printf("%p\n", x) ;
}

void bar(char x[])
{
printf("%p\n", x) ;
}

void barv(void * x)
{
printf("%p\n", x) ;
}

int main()
{
char x[3] ;

printf("%p\n", x ) ;
printf("%p\n", &x ) ;
printf("%p\n", &x[0] ) ;

foo( x ) ;
foo( &x[0] ) ;

bar( x ) ;
bar( &x[0] ) ;
barv( &x ) ;

return 0 ;
}
```
```\$ ./t
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
0x7fff293a7110
```
2. ### Reinsaid

I agree with Sam Kendall.

Maybe you’ll understand that this ‘inconvenient inconsistency’ is a left over from back in the old days. Until recent object oriented programming came along people put strings in arrays like this:

char szName[128];
char szAnotherString[128];

Then using the ansi c string functions like strcpy would raise an error if you compile:

strcpy(szAnotherString, szName);

Because strcpy is defined like

char *strcpy(
char *strDestination,
const char *strSource
);

Well ok then, let’s use:

strcpy(&szAnotherString, &szName);

Another error arises (by a consistent compiler), you get a pointer to a char[128].

So this is our best attempt:

strcpy(&szAnotherString[0], &szName[0]);

Yes it is! This result in exactly two pointers to a char.
But this is a very inconvenient way to pass on a string each and every time, so the compiler will convert (all of these) automatically for you.

Kind regards,
Rein

• ### peeterjootsaid

Rein,

I can’t produce your claimed compilation error scenerio?

```\$ gcc -ansi -c t.c
\$ cat t.c
#include <stdio.h>

char szName[128];
char szAnotherString[128];

void foo()
{
strcpy(szAnotherString, szName);
}
```
• ### Reinsaid

That’s because the compiler automatically converts for you š

All of the scenario’s I mentioned would flag as an error with a imaginary compiler that would not convert for you. Don’t know if you can disable these auto conversions, depends on the compiler I guess. You look for a command line switch if you really want to. But I can’t see the point in that anyway.

Just to clarify once more:

strcpy(szAnotherString, szName);
passing on char arguments to a function that accepts only char* arguments -> NOT OK

strcpy(&szAnotherString, &szName);
passing on char[128]* arguments to a function that accepts only char* arguments -> NOT OK

strcpy(&szAnotherString[0], &szName[0]);
passing on char* arguments to a function that accepts only char* arguments -> OK

3. ### hallysaid

very easy method to learn.