Массив и Массив [0] путаница - PullRequest
1 голос
/ 08 марта 2020

В следующем C коде:

char test[] ={'T','e','s','t'};

printf("%d\n",test == &test[0]); // Returns 1 - Okay as array varaible holds address of first element

Так не должно ли следующее печатать одно и то же?:

printf("value of test %c\n", test); // prints - '|' not even in the array
printf("value of test[0] %c\n", test[0]); // prints - 'T'

Даже если это печатает разные значения :

printf("value of test %p\n", test); // contains a address 0x7ffee9b22b7c
printf("value of test[0] %p\n", test[0]); // also conatains 0x100

Что происходит?

спасибо

Ответы [ 3 ]

2 голосов
/ 08 марта 2020

Вы как бы ответили на свой вопрос в первом примере:

test == &test[0]

test != test[0] // otherwise, test[0] would have to be equal to &test[0]

Т.е. значение из test (интерпретируется как указатель) равно адресу из test[0]. Поэтому ваши следующие примеры не могут быть правдой, поскольку это будет означать, что для любого из них его значение будет равно его собственному адресу, что не имеет смысла!

(Примечание: следующие адреса являются примерами курс.)

enter image description here

Примечание. В целях понимания вашей первоначальной проблемы нормально смотреть на test как char*, и, следовательно, &test как char**. Однако в действительности это немного сложнее, и test на самом деле имеет тип char(*)[4]. Это имеет значение, например, с sizeof.

1 голос
/ 08 марта 2020

вы можете путать себя с тем, как вы печатаете. Попробуйте это и посмотрите, легче ли следовать.

#include <stdio.h>


int main(){

    char test[] = "Test\n\0"; // an array that contains char values
    char *testptr; // a pointer that can point to a place in memory that contains a char value


    printf(test); // by default it will print all of the char values starting with test[0]

    testptr = &test[2]; // the pointer now points to the third position in the char array

    printf(testptr); // print the test array starting with the pointers position

}
0 голосов
/ 08 марта 2020

Распад указателя

Хотя указатели и массивы являются разными типами переменных, переменная массива часто неявно преобразуется как указатель на свой первый элемент. Это называется массив до затухания указателя .

Это то, что происходит в сравнении, которое вы проводите между test и &test[0]: test распадается на указатель, который можно сравнить с &test[0], и их значение равно

Что происходит в ваших printf вызовах?

printf("value of test %c\n", test); // prints - '|' not even in the array
printf("value of test[0] %c\n", test[0]); // prints - 'T'

Первые из них со спецификатором преобразования %c преобразуют аргумент в unsigned char и печатает символ. В первой строке вы печатаете test как символ, а во второй строке вы печатаете test[0] как символ.

Тип test[0] действительно char, поэтому правильный символ ( T) печатается. Однако тип test - это массив char, который в этом случае также распадается на указатель. При выполнении теста этот указатель имеет значение 0x7ffee9b22b7c. Затем это значение преобразуется в unsigned char, поэтому последний байт вашего указателя сохраняется, в этом случае это 7c, что является кодом ASCII для символа |.

Обратите внимание, что, поскольку это зависит от значения указателя, очень вероятно, что вы будете получать разные символы при каждом запуске программы (некоторые из них могут даже не быть печатными символами).

Два результата отличаются, потому что это разные вещи: один - символ, а другой - указатель (в данном случае указатель на символ).

test[0] - это значение он содержится в начале массива, а test оценивается как указатель на первый элемент (а затем принудительно преобразуется в символ). Как вы отмечали ранее, test эквивалентно &test[0], а не - test[0].

test[0] эквивалентно *test (или *(test + 0)) , В общем случае в массиве array[i] будет эквивалентно *(array +i).

...