2015-02-09 2 views
0
#include <cstdlib> 
#include <iostream> 

using namespace std; 

void f(int k[0]){ --k[1]; } 
void g(int *k){(*(--k))++;} 
void h(int k[1]){--k;} 

int main(){ 
    int k[]={1,2,3,4}; 
    f(k+2); 
    g(k+2); 
    h(k+2); 
    for (int i = 1; i < 4; i++) 
     cout << k[i]; 
} 

Правильный вывод 333, но я думал, что это 334. Я не понимаю, что именно происходит в функции f с инструкцией --k[1]. Я мог бы согласиться с правильным выходом, если код был k[0]--. Какая разница? Благодарякакие C++ указатели делают в этом коде

+0

Печать 'k [4]' - неопределенное поведение. – timrau

+3

Он никогда не печатает k [4] – rcrmn

+3

Не имеет значения, что делает этот код, потому что вещь, которую вы должны сделать, увидев ее, отследит автора и избивает их, пока они не плачут, как ребенок. Затем вы должны заставить их перекодировать его так, как это сделал бы профессиональный разработчик, а не безумная обезьяна на амфетаминах. – paxdiablo

ответ

1

--k[1] вычитает значение в k[1], и с учетом f(k+2) означает f() -локальных k указует на вызывающий абонент (т.е. main()-х) k[2], а 1 и 2 индексов добавить, что вы на самом деле декремент вызывающего абонента k[3] от 4 до 3.

k[0]-- будет уменьшать значение переменной на *k, что для f будет в качестве значения k[2] в контексте вызывающего абонента.

Важным прозрений для понимания этого кода являются:

  • все функции f, g и h в конечном итоге получить указатель на int, и их понятие «k» является полностью независимым от понятия о вызывающем абоненте из k, в частности, - это смещение 2 int S дальше в массив k вызывающего абонента,

  • operator precedence: specificall y, применяется префикс декремента после подписи на основе массива в --k[1].

Это говорит, что paxdiablo, безусловно, имеет смысл ... ;-).

+0

, так что писать иначе: 'cout << (--k [1])': он сначала делит элемент в позиции 1, а затем печатает его; и: 'cout << (k [1] -)': он сначала печатает исходное значение в позиции 1, а затем уменьшает его. Правильно? – bogALT

+0

@bogALT: в C++ нет 'System.out.print', но если вы использовали' std :: cout <<', тогда да - ваши утверждения истинны; будучи nit-picky, второй оператор * копирует * значение, уменьшает его, а затем печатает копию. –

+0

Вы правы, экзамен имеет несколько упражнений на Java, а некоторые - на C++, поэтому я его смешивал. извините – bogALT

0

Что этот код делает это:

  1. Передаёт массив, начиная с 3-го элемента в k[] к f. f принимает 1-мерный массив и уменьшает его 2-й элемент (в этом случае он будет k[4], который изменит его значение от 4 до 3).

  2. Пропустите указатель 3-го элемента в k[] на g. g берет указатель на целое число или массив и сначала уменьшает значение указателя (теперь становится указателем на 2-й элемент k[]), а затем увеличивает значение того, что указало, меняя его с 2 на 3.

  3. Передайте массив, начиная с 3-го элемента в k[], до h. `h получает 1-мерный массив и уменьшает указатель на массив (а не значение, на которое он указывает), таким образом не изменяя значения остроконечного массива.

+1

'f' не принимает одномерный массив; он принимает указатель. То же самое для 'h'. –

1

Во-первых, все три функции имеют точно такую ​​же подпись. Было бы менее запутанным, если бы было написано:

void f(int* pi){ --pi[1]; } 
void g(int* pi){(*(--pi))++;} 
void h(int* pi){--pi;} 

(я изменил название аргумента, чтобы избежать двусмысленности в следующих discutions.)

Кроме того, конечно: a[b], по определению, *(a + b), и что любая операция по k преобразует его из int[4] в int*, указывая на первый элемент.

Таким образом, мы получаем следующие результаты:

f(k + 2); 
// In f, pi is k + 2, so `pi[1]` is *(k + 3). 
// After f, k = { 1, 2, 3, 3 } 
g(k + 2); 
// In g, pi starts out as k + 2; it is then decrementd to give k + 1 
// After g, k = { 1, 3, 3, 3 } 
h(k + 2); 
// In h, pi is k + 2. A local copy of k + 2, so h doesn't change 
// k at all. 

Результаты, которые k является { 1, 3, 3, 3 } после четырех операций.

0

Р и изменяют значения, в то время как ч модифицирует адрес:

f(int k[0]){ --k[1]; } 

е принимать один параметр, массив Int; k [1] в этом случае совпадает с k ++; функция уменьшает значение элемента, расположенного на следующем адресе, и тот, который проходит в качестве аргумента. Итак, вы уменьшаете k [3] в своем главном.

g относительно прямо вперед, и я думаю, вы поняли это.

ч подобны е

h(int k[1]){--k;} 

ч принимают Int массив в качестве входных данных, и это уменьшает адрес, передаваемый в качестве аргумента.

Надеется, что это помогает

1

С небольшим изменением в коду, вы можете увидеть что каждый шаг делает:

#include <cstdlib> 
#include <iostream> 
using namespace std; 

int *globk; 
void dumpk(int *pk) { 
    cout << "Array:"; 
    for (int i = 0; i < 4; i++) 
     cout << ' ' << globk[i]; 
    cout << ", k at index " << (pk-globk) << '\n'; 
} 

void f(int k[0]) { dumpk(k); --k[1]; dumpk(k); } 
void g(int *k) { dumpk(k); (*(--k))++; dumpk(k); } 
void h(int k[1]) { dumpk(k); --k;  dumpk(k); } 

int main(){ 
    int k[]={1,2,3,4}; 
    globk = k; // save for detecting where k is 

    f(k+2); 
    g(k+2); 
    h(k+2); 

    // slightly prettier output. 

    for (int i = 1; i < 4; i++) 
     cout << k[i] << ' '; 
    cout << '\n'; 
} 

Выходной сигнал, который показывает, что каждый шаг делает:

Array: 1 2 3 4, k at index 2 
Array: 1 2 3 3, k at index 2 
--k[1];   // -- array VALUE at INDEX 3 (2+1) down to 3 

Array: 1 2 3 3, k at index 2 
Array: 1 3 3 3, k at index 1 
(*(--k))++;  // -- POINTER to [1], then ++ that VALUE up to 3 

Array: 1 3 3 3, k at index 2 
Array: 1 3 3 3, k at index 1 
--k;   // Simply -- POINTER with no change to any VALUE 
+0

большое спасибо – bogALT

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