指针还是地址?

Pointer or address?

// 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;
}

以上代码来自cs50 2018第3讲。 t[i] = s[i] 部分让我感到困惑。据我所知,当我们说 char *t 时, t 将存储分配的内存第一部分的地址。那么 t[i] 不是给我们 t[i] 位置的内存地址吗?如果是这样,我们是不是应该写
*t[i] = s[i] 更改 t[i] 的值 ?

不,[] 数组索引运算符 取消引用 指针并求值为值本身,而不是其地址。表达式 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

t[i] 实际上给你数组的第 i 个元素。它的工作原理与 s[i] 相同,后者具有相同的类型。

语法 t[i]*(t + i) 完全相同。换句话说,执行指针运算以获得指向所需元素的指针,然后解引用结果以获取实际元素。

char *s = ...;
char *t = ...;
...
t[i] = s[i];

t[i] 是一个 左值 ,一个引用对象的表达式。过于简单化一点 [*],如果它出现在赋值的左侧(就像它在这里所做的那样),它指的是一个特定的 char 对象,并且赋值会更新该对象的值。 s[i] 类似,但它出现在赋值的右侧,因此它产生对象的 value

本质上是一样的:

int x;
int y;
y = x;

xy 都是对象的名称,它们都是左值。左侧的 y 指的是对象。右侧的 x 产生存储在对象中的值。

[*] 过于简单化的是,除了赋值的左侧之外,还有其他上下文,其中左值引用对象而不是产生其值。

[] 运算符的定义方式(见 comp.lang.c FAQ)第 6 节数组和指针之间的关系),但在这种情况下,你真正需要知道的是 s[i]t[i] 是对象的名称。

C 标准 N1570 draft 的第 6.3.2.1 节

中有血淋淋的细节