// 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]
的值?
答案 0 :(得分:4)
否,[]
数组索引运算符取消引用指针,并求值到值本身,而不是它的地址。表达式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
答案 1 :(得分:2)
t[i]
实际上为您提供了数组的第i
个元素。它与s[i]
(具有相同的类型)相同。
语法t[i]
与*(t + i)
完全相同。换句话说,执行指针算术以获取指向所需元素的指针,然后将结果取消引用以获取实际元素。
答案 2 :(得分:0)
char *s = ...;
char *t = ...;
...
t[i] = s[i];
t[i]
是 lvalue ,它是引用对象的表达式。如果位[*]出现在分配的左侧(如此处所做的那样),则将其过度简化,它引用的是特定的char
对象,并且分配会更新该对象的值。 s[i]
与之类似,但是它出现在赋值的右侧,因此产生对象的 value 。
基本上与以下内容相同:
int x;
int y;
y = x;
x
和y
都是对象的名称,并且都是左值。左侧的y
是指对象。右侧的x
产生存储在对象中的值。
[*]过于简单化是,除了赋值的左手以外,还有其他上下文,其中左值引用对象而不是产生对象的值。
这里定义[]
运算符的方式还有很多事情(有关数组和指针之间的关系,请参见第comp.lang.c FAQ节),但是在这种情况下,您真正需要的只是知道s[i]
和t[i]
是对象的名称。
C标准N1570 draft的第6.3.2.1。节中有详细内容。