If your code compiled without warnings, you are not making full use of your compiler. It will help you if you ask it to do so. Learn how to make it compile with warnings, and learn how to fix the problems it diagnoses. I compiled the code below with one or the other of these commands:
gcc -O3 -g -std=c99 -Wall -Wextra -m64 array-stuff.c -o array-stuff
gcc -O3 -g -std=c99 -Wall -Wextra -m32 array-stuff.c -o array-stuff
That's a good starting point for clean code with GCC. Indeed, -Wall
without -Wextra
is pretty good too.
Here's an adaptation of your code (in a file array-stuff.c
) — although most of it is different:
#include <stdio.h>
#include <inttypes.h>
int main(void)
{
// DC4M = Doesn't compile for me, because I compile with stringent warnings
char ar[16] = { 'a', 'b', 'c', '\0' }; // Note explicit size
printf("%-18s %s\n", "Code:", "char ar[16] = { 'a', 'b', 'c', '\0' };");
//printf("argument: &ar %s\n", &ar); // DC4M
printf("argument: &ar[1] %s\n", &ar[1]);
printf("%-18s 0x%" PRIXPTR "\n", "ar:", (uintptr_t)ar);
printf("%-18s 0x%" PRIXPTR "\n", "&ar:", (uintptr_t)&ar);
printf("%-18s 0x%" PRIXPTR "\n", "(ar+1):", (uintptr_t)(ar+1));
printf("%-18s 0x%" PRIXPTR "\n", "(&ar+1):", (uintptr_t)(&ar+1));
printf("%-18s 0x%" PRIXPTR "\n", "&ar[1]:", (uintptr_t)(&ar[1]));
printf("%-18s 0x%" PRIXPTR "\n", "&(ar[1]):", (uintptr_t)(&(ar[1])));
printf("%-18s 0x%" PRIXPTR "\n", "(&ar)[1]:", (uintptr_t)((&ar)[1]));
printf("%-18s %zu\n", "sizeof(ar):", sizeof(ar));
printf("%-18s %zu\n", "sizeof(&ar):", sizeof(&ar));
printf("%-18s %zu\n", "sizeof(void*):", sizeof(void*));
printf("%-18s %zu\n", "sizeof(ar[1]):", sizeof(ar[1]));
printf("%-18s %zu\n", "sizeof(&ar[1]):", sizeof(&ar[1]));
printf("%-18s %zu\n", "sizeof(&(ar[1])):", sizeof(&(ar[1])));
printf("%-18s %zu\n", "sizeof((&ar)[1]):", sizeof((&ar)[1]));
{
char a = 's';
char *pa = &a;
printf("%-18s %s\n", "Code:", "char a = 's';");
printf("%-18s %s\n", "Code:", "char *pa = &a;");
//printf("argument: &pa %c\n", &pa); // DC4M
printf("%-18s 0x%" PRIXPTR "\n", "&pa:", (uintptr_t)&pa);
printf("%-18s 0x%" PRIXPTR "\n", "&a:", (uintptr_t)&a);
printf("%-18s 0x%" PRIXPTR "\n", "pa:", (uintptr_t)pa);
}
{
char *pa = &ar[0];
char **ppa = &pa;
//printf("argument: &pa %s\n", ppa); // DC4M
printf("%-18s %s\n", "Code:", "char *pa = &ar[0];");
printf("%-18s %s\n", "Code:", "char **ppa = &pa;");
printf("%-18s 0x%" PRIXPTR "\n", "&pa:", (uintptr_t)&pa);
printf("%-18s 0x%" PRIXPTR "\n", "ppa:", (uintptr_t)ppa);
printf("%-18s 0x%" PRIXPTR "\n", "*ppa:", (uintptr_t)*ppa);
printf("%-18s 0x%" PRIXPTR "\n", "&ppa:", (uintptr_t)&ppa);
}
}
This is the output from a Mac OS X 10.7.4 machine with a 64-bit compilation:
Code: char ar[16] = { 'a', 'b', 'c', '
argument: &ar[1] bc
ar: 0x7FFF6C9DE570
&ar: 0x7FFF6C9DE570
(ar+1): 0x7FFF6C9DE571
(&ar+1): 0x7FFF6C9DE580
&ar[1]: 0x7FFF6C9DE571
&(ar[1]): 0x7FFF6C9DE571
(&ar)[1]: 0x7FFF6C9DE580
sizeof(ar): 16
sizeof(&ar): 8
sizeof(void*): 8
sizeof(ar[1]): 1
sizeof(&ar[1]): 8
sizeof(&(ar[1])): 8
sizeof((&ar)[1]): 16
Code: char a = 's';
Code: char *pa = &a;
&pa: 0x7FFF6C9DE560
&a: 0x7FFF6C9DE56F
pa: 0x7FFF6C9DE56F
Code: char *pa = &ar[0];
Code: char **ppa = &pa;
&pa: 0x7FFF6C9DE558
ppa: 0x7FFF6C9DE558
*ppa: 0x7FFF6C9DE570
&ppa: 0x7FFF6C9DE550
And this is the output from a 32-bit compilation:
Code: char ar[16] = { 'a', 'b', 'c', '
argument: &ar[1] bc
ar: 0xC008A670
&ar: 0xC008A670
(ar+1): 0xC008A671
(&ar+1): 0xC008A680
&ar[1]: 0xC008A671
&(ar[1]): 0xC008A671
(&ar)[1]: 0xC008A680
sizeof(ar): 16
sizeof(&ar): 4
sizeof(void*): 4
sizeof(ar[1]): 1
sizeof(&ar[1]): 4
sizeof(&(ar[1])): 4
sizeof((&ar)[1]): 16
Code: char a = 's';
Code: char *pa = &a;
&pa: 0xC008A668
&a: 0xC008A66F
pa: 0xC008A66F
Code: char *pa = &ar[0];
Code: char **ppa = &pa;
&pa: 0xC008A664
ppa: 0xC008A664
*ppa: 0xC008A670
&ppa: 0xC008A660
When you understand how the various numbers were arrived at, you will be well on your way to understanding things.
Note that &array[1]
is interpreted as &(array[1])
; it is different from (&array)[1]
in type and size. The postfix operators such as array subscripting bind more tightly than the unary operators such as the address (&
) and indirection (*
) operators.
`s :) – Blorgbeard Jul 19 '12 at 02:17