Указатель или адрес? - PullRequest
       9

Указатель или адрес?

0 голосов
/ 06 ноября 2018
// Capitalizes a copy of a string while checking for errors

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    // Get a string
    char *s = get_string("s: "); //this is in the cs50.h
    char *t = malloc((strlen(s) + 1) * sizeof(char));

    // Copy string into memory
    for (int i = 0, n = strlen(s); i <= n; i++)
        t[i] = s[i];

    return 0;
}

Приведенный выше код взят из лекции № 3 2018 г.г. t[i] = s[i] часть смутила меня. Как я знаю, когда мы говорим char *t, t будет хранить адрес первой части памяти, которая была выделена. Так t[i] не дает нам адрес памяти в t[i] месте? Если это так, разве мы не должны писать
*t[i] = s[i] чтобы изменить значение t[i]?

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

t[i] фактически дает вам i-й элемент массива. Он работает так же, как s[i], который имеет тот же тип.

Синтаксис t[i] точно такой же, как *(t + i). Другими словами, арифметика указателя выполняется для получения указателя на требуемый элемент, затем результат разыменовывается для получения фактического элемента.

0 голосов
/ 06 ноября 2018
char *s = ...;
char *t = ...;
...
t[i] = s[i];

t[i] - это lvalue , выражение, которое относится к объекту. Чрезмерно упрощая бит [*], если он появляется в левой части назначения (как здесь), он ссылается на конкретный объект char, и назначение обновляет значение этого объекта. s[i] аналогично, но оно появляется справа от назначения, поэтому оно возвращает значение объекта.

Это по сути то же самое, что и:

int x;
int y;
y = x;

x и y являются именами объектов, и они оба lvalues. y в левой части относится к объекту. x справа возвращает значение, сохраненное в объекте.

[*] Упрощение заключается в том, что существуют иные контексты, кроме левой части присваивания, в которых lvalue ссылается на объект, а не дает его значение.

Здесь немного больше рассказывается о том, как определяется оператор [] (см. Раздел 6 comp.lang.c FAQ ) о взаимосвязях между массивами и указателями), но в этом В этом случае все, что вам действительно нужно знать, это то, что s[i] и t[i] являются именами объектов.

Подробные сведения приведены в стандарте C, N1570, черновик , раздел 6.3.2.1.

0 голосов
/ 06 ноября 2018

Нет, оператор индекса массива [] разыменовывает указатель и вычисляет само значение, а не его адрес. Выражение s[i] эквивалентно выражению *(s + i). Если вам нужен адрес элемента с индексом i, вам необходимо использовать оператор &, как в &s[i] (что эквивалентно s + i).

int array[] = { 10, 20, 30, 40 };  // create an array for illustration
int *ptr = array;                  // array type decays to a pointer

// these print the same thing: the address of the array element at index 2
printf("%p\n", ptr + 2);      // pointer arithmetic
printf("%p\n", &ptr[2]);      // array index operator followed by address-of operator

// these print the same thing: the element at index 2 (= 30)
printf("%d\n", *(ptr + 2));   // pointer arithmetic followed by dereference operator
printf("%d\n", ptr[2]);       // array index operator
...