2016-01-25 2 views
4

Я пытаюсь скомпилировать эту программу без предупреждения,Неправильное предупреждение формата в этом гр программе

#include<stdio.h> 
int main() 
{ 
    int arr[] = {1,2,3}; 
    printf("value1 = %d value2 %d\n", *(&arr+1), *(arr+1));//here is the warning 
    return 0; 
} 

Но я получаю время компиляции предупреждения

warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat] 

Я компиляцию свою программы на 64 бит ubuntu machine gcc версии 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5).

+0

' * (& arr + 1) '-> адрес' arr' (как указатель на массив из 3 'int'), смещенный размером массива из 3 'int', а затем разыменованный для получения массива из 3 'int', который затем распадается на указатель на 'int' (который указывает на 4-й« int »после первоначального начала' arr', или 1-й «int» второго массива 'int' начиная с адреса 'arr'). – Dmitri

ответ

6

&arr принимает адрес массива, это указатель на массив (не путать с указателем на 1-й элемент). Он имеет тип int(*)[3].

Затем вы выполняете арифметику указателя на этом указателе массива. Так как он указывает на массив из 3 целых чисел, то &arr + 1 будет означать «плюс размер одного целого массива», и вы в конечном итоге указываете только на объявленный массив, что не имеет никакого смысла.

Затем вы берете содержимое указателя массива с помощью *. Затем вы снова получите массив. Когда вы массив в выражении, он распадается на указатель на свой первый элемент, int*. Что несовместимо с int, поэтому ошибка.

Я предполагаю, что вы, вероятно, пытались сделать либо &arr[0] + 1, либо arr + 1, что и означает одно и то же.

+0

Да, я пытаюсь сделать то же самое. То, что я искал, является подходящим объяснением этого предупреждения. * (& arr [0]) также дает мне такое же предупреждение. – mrigendra

+0

Я неправильно понял аргумент 2 как * (arr + 1), и предупреждение из-за него. – mrigendra

1

arr имеет тип int (*)[3], кроме int *, хотя в большинстве случаев имена массивов распадаются на указатели на первые элементы, то есть в вашем втором случае &arr[0], и это именно то, почему ваш value2 выводится нормально.

Однако, когда arr является аргументом оператора &, он не разрушается. В результате &arr+1 имеет эквивалентное значение как &arr[0]+3. Это связано с тем, что sizeof &arr равен sizeof (int (*)[3]), что дает 3. Следовательно, при попытке вывода value1 вы фактически получаете доступ к &arr[3], тип которого int *. Это &arr[3], а не arr[3], потому что когда вы разыскиваете что-то типа int (*)[3], оно распадается на указатель.

Как вы можете видеть, предупреждение действительно пытается спасти вас от потенциальной ошибки.

Смотрите также: Exception to array not decaying into a pointer?

1

Шаг за шагом:

arr имеет тип "массив 3 Int".

int arr[] = {1,2,3}; 

&arr имеет тип "указатель на массив 3 ИНТ".

&arr + 1 также является «указателем на массив 3 из int».

*(&arr+1) - тип "массив 3 из".

Когда массив передается функции, происходит преобразование.Адрес первого элемента массива передается, а не сам массив. В этом случае он имеет тип int *.

"%d" ожидает соответствующий int, поэтому компилятор предупреждает:

формат '% d' ожидает, что аргумент типа 'Int', но аргумент 2 имеет тип 'Int *'

Смежные вопросы