[英]Pointers, addresses and arrays in C
所以我知道指针是存储其他一些变量地址的变量。 但是让我感到困惑的是:我知道在大多数上下文中使用数组的名称会将其衰减到元素的基地址。 但是我在这里感到困惑:当我们声明一个数组时说int arr[5]
,然后说scanf("%d",arr+1)
,这里arr
是一个地址,对吧? 我们没有明确地将它存储在任何变量中,即指针。 那么arr+1
算术是如何与指针算术类似的呢? 这也是: *(arr+1)
会给我们地址arr+1
中的值。 我确实意识到我们可以取消引用地址,但是在这里我发现很难使用它,因为我有点失去了“嘿,这个指针指向这个地址......”在这里。 我的最后一个问题是,这是我们可以将地址与计算机中的随机值区分开来的确切方法吗? 在这种情况下,就像arr+1
导致下一个整数的地址,而不是正常的+1
(基本上是指针算术)。
我希望我的问题没有任何歧义。
您的问题始于这种误解:
所以我知道指针是存储其他一些变量地址的变量。
“指针”是一个类型类别。 有指针类型的值,也称为“地址”,也有声明为保存这些值的变量。 这完全类似于存在int
类型的值和声明为保存int
值的变量。 此外,正如我们可能将int
值或int
变量称为“an int”一样,人们可以并且确实将指针值和指针变量称为“指针”。
此外,说指针值是变量的地址有点不准确和有点误导。 它们是对象的地址,尽管范围内的变量确实表示对象,但并非所有对象都对应于变量。
当我们声明一个数组时说 int
arr[5]
,然后说scanf("%d",arr+1)
,这里 arr 是一个地址,对吧?
当scanf
调用被求值时, arr
的数组值会自动转换为指针值,即第一个数组元素的地址。
我们没有明确地将它存储在任何变量中,即指针。
您无需将指针值存储在变量中即可在表达式中使用它。 事实上,恰恰相反:如果你想在算术表达式中使用指针变量的值,你必须首先从中读取值——这个过程称为“左值转换”。 这同样适用于涉及大多数运算符的所有类型和表达式的变量。 大多数操作都是根据values定义的,而变量只是传达这些操作的一种方式。
那么
arr+1
算术是如何与指针算术类似的呢?
这里没有“类似”。 它是指针算术。 arr
会自动转换为指针值。 该值是加法运算符的合适操作数,前提是另一个操作数是整数类型。 这是一个指针算术表达式。
这也是:
*(arr+1)
会给我们地址arr+1
中的值。
是的,尽管说地址arr+1
处的值会更惯用。
我确实意识到我们可以取消引用一个地址,但是在这里我发现很难使用它,因为我有点失去了“嘿,这个指针指向这个地址..”
好吧,大多数人会将*(arr+1)
写为arr[1]
,这是 100% 等效的,但更易于阅读且通常更清晰。 除此之外,我不确定你在问什么,如果有的话。
这是我们可以将地址与计算机中的随机值区分开来的确切方法吗? 在这种情况下,就像
arr+1
导致下一个整数的地址,而不是正常的+1
(基本上是指针算术)。
C 程序如何解释给定的字节序列取决于它赋予该序列的数据类型。 这正是数据类型的功能。 在底层物理内存中没有可辨别的差异,这都是程序解释的一种方式。 如果x
具有指针类型,则x+1
是指针算术,包括从数组自动转换的结果。 如果x
的类型为int
、 long
等,则为整数加法。如果x
的类型为double
、 float
或long double
,则为浮点加法。
假设我们有:
int n = 1;
int arr[100];
arr + n
:是的,这是一个地址。arr + n
:是的,我们在这里做指针运算。arr + n
与&arr[n]
相同。*(arr + n)
与arr[n]
相同。指针算术示例:
假设一个int
的大小是 4 个字节,而arr
是地址0x10000
:
arr + n
是0x10000
+ n * 4
arr+2
是地址0x10008
您的最后一个问题有些不清楚,但是如果您理解了上述内容,则应该很清楚。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.