2016-10-08 18 views
2
#include <stdio.h> 

void main() 
{ 
int a[]={1,2,3,4}; 

printf("%u %u ",a ,&a);   //a 
printf("%d %d ", *a ,*&a);  //b 
} 

В ATH линии выход a и &a такой же адрес, но в BtH линии *&a не дает мне ответ как 1.Указатели массива в C

Я знаю, что &a означает указатель на массив целых чисел, но поскольку адрес тот же, он должен печатать 1 вправо?

+0

Читать раздел 6 из [comp.lang.c] (http://www.c-faq.com/). И 'void main()' должен быть 'int main (void)'. И вам не хватает '#include '. –

+0

Использование '% u' в' printf' для печати значений указателя - неопределенное поведение (и это может легко привести к бессмысленным результатам на практике). Для указателей печати есть '% p'. И вы должны преобразовать указатели в 'void *' перед отправкой их в 'printf'. – AnT

ответ

5

a распадается на указатель на первый элемент массива.
&a - указатель на массив из 4 int s.

Несмотря на то, что числовые значения двух указателей одинаковы, указатели не одного типа.

Тип a (после его разложения указателю) int*.
Тип &a является указателем на массив из 4 int s - int (*)[4].

Тип *a - int.
Тип *&a - это массив из 4 целых чисел - int [4], который распадается на указатель на первый элемент вашего выражения.

Вызов

printf("%d %d ", *a ,*&a); 

эквивалентно:

printf("%d %d ", *a , a); 

BTW, Вы должны использовать %p для указателей. В противном случае вы вызываете неопределенное поведение. Увеличьте уровень предупреждения вашего компилятора, чтобы избежать таких ошибок.

1

Принимая более простую версию кода следующим образом:

#include <stdio.h> 

void main() 
{ 
int a[]={1,2,3,4}; 

printf("%d %d ", *a ,*&a);  //b 
} 

Если я скомпилировать этот код я получаю это предупреждение:

test1.c 
D:\Temp\test1.c(7): warning C4477: 
    'printf' : format string '%d' requires an argument of type 'int', but variadic 
       argument 2 has type 'int *' 
Microsoft (R) Incremental Linker Version 14.00.23506.0 
Copyright (C) Microsoft Corporation. All rights reserved. 

Это предупреждающее сообщение дает вам причину, почему это не работает как вы ожидаете.

Теперь я могу изменить этот код, чтобы удалить эти предупреждения, и я в конечном итоге с кодом, как это:

#include <stdio.h> 

void main() 
{ 
int a[]={1,2,3,4}; 

int (*p)[4] = &a; 

printf("\n%u %u ", *a ,*p[0]);  //b 
} 

Этот код чистые компилирует и при запуске вы получите ожидаемый результат:

1 1 
0

последний проект стандарта C предполагает, что

Если операнд является результатом одноместной оператора *, не оценен оператор или оператор &, а результат , как если бы оба были опущены ...

Однако вышеупомянутый пункт относится к случаю, когда это & *, не * &. Попытайтесь думать об этом так:

&a // pointer to array[4] of integers 
*(&a) // array[4] of integers 
------------------------------------------ 
    a // array[4] of integers 

Обратите внимание, что оператор * удаляет один слой указателей. Поэтому *(&a) идентичен aсемантически. В этом случае a преобразуется в выражение с типом pointer to an integer, потому что другой пункт предполагает, что

исключением случаев, когда это операнд оператора SIZEOF, оператор _Alignof или одноместной & оператора, или является строковый литерал, используемый для инициализации массива, выражение, которое имеет тип '' array of type '', преобразуется в выражение с указателем типа '' to type '', которое указывает на начальный элемент объекта массива и не является lvalue ...

В заключение следует отметить тот факт, что a Естественным является ddress a (не элемент внутри).

0

Пожалуйста, сделать еще одну вещь в вашем коде:

printf("%u %u ",a+1 ,&a+1); //a1