C++ 在非数组指针上建立索引时的类型确定&读取超过最后一个元素

C++ 在非数组指针上建立索引时的类型确定&读取超过最后一个元素,c++,pointers,indexing,C++,Pointers,Indexing,我知道foo将是int*类型。 因为foo是一个指针,所以可以使用[]对其进行索引。 因此,foo[0]将与*foo相同,类型为int 我不明白为什么foo[1]是int。 我知道C++不关心你“走出界限”,并且未定义行为是预期的,但是为什么FoO(1)也会是int型的? 因为foo是一个int*,所以它只接受后面的4个字节并假定它是一个int*?在这个表达式中 int main() { auto foo = new int; } 这里使用了指针算法。此表达式的计算方式如下 foo[1

我知道foo将是int*类型。 因为foo是一个指针,所以可以使用[]对其进行索引。 因此,foo[0]将与*foo相同,类型为int

我不明白为什么foo[1]是int。 我知道C++不关心你“走出界限”,并且未定义行为是预期的,但是为什么FoO(1)也会是int型的? 因为foo是一个int*,所以它只接受后面的4个字节并假定它是一个int*?

在这个表达式中

int main()
{
    auto foo = new int;
}
这里使用了指针算法。此表达式的计算方式如下

foo[1] 
子表达式foo+1的类型为int*。因此,在形式上,完整表达式的类型为int。也就是说,子表达式foo+1指向的内存被解释为在该表达式中存储int类型的对象。

int main()
{
    auto foo = new int;
}
这里使用了指针算法。此表达式的计算方式如下

foo[1] 
子表达式foo+1的类型为int*。因此,完整表达式的形式是int类型。也就是说,子表达式foo+1指向的内存被解释为存储int类型的对象

因为foo是int*,所以它是否只需要接下来的4个字节并假设它是int

我想说,这是一个简单的方式来看待它

基本上,C++的类型系统在编译时是固定的。抛开诸如虚拟函数或动态映射之类的东西,C++不验证或猜测它被认为是什么样的类型来对待记忆。当你深入到像int这样的基本类型时,它们不携带任何元信息,人们可以根据这些信息判断内存中的某个4字节是int还是float或char[4]或其他

例如,is int*指向的内存被视为int。在组成编译程序的指令中,这是一种非常简单有效的工作方式

这也导致了所有关于从一种类型铸造到另一种类型时要谨慎的建议,如果可能的话,通常要避免。因为通过强制转换,您可以强制内存被视为与正常情况不同的类型—本质上是告诉编译器按照我说的做,因为我比您更了解。如果你知道自己在做什么,这可以用来耍聪明的把戏。但是,如果你错了,那么没有什么能阻止你射中自己的脚

因为foo是int*,所以它是否只需要接下来的4个字节并假设它是int

我想说,这是一个简单的方式来看待它

基本上,C++的类型系统在编译时是固定的。抛开诸如虚拟函数或动态映射之类的东西,C++不验证或猜测它被认为是什么样的类型来对待记忆。当你深入到像int这样的基本类型时,它们不携带任何元信息,人们可以根据这些信息判断内存中的某个4字节是int还是float或char[4]或其他

例如,is int*指向的内存被视为int。在组成编译程序的指令中,这是一种非常简单有效的工作方式


这也导致了所有关于从一种类型铸造到另一种类型时要谨慎的建议,如果可能的话,通常要避免。因为通过强制转换,您可以强制内存被视为与正常情况不同的类型—本质上是告诉编译器按照我说的做,因为我比您更了解。如果你知道自己在做什么,这可以用来耍聪明的把戏。但是,如果你错了,那么没有什么能阻止你射中自己的脚。

foo可以被看作是指向单元素数组的第一个元素的指针。它类似于例如int数组[1];int*foo=&数组[0];。但是,C++没有对数组或指针进行任何类型的边界检查。因此,您可以轻松地访问超出边界的元素,如foo[1]。这将导致未定义的行为。但是,即使超出范围,基类型仍然是相同的,因为数组中的每个元素都是相同的类型。如果foo被声明为指针类型,例如int*,那么表达式foo[x]被解释为*foo+x。x的值是多少并不重要。foo+x可能指向有效的内存位置,也可能不指向。由您决定是否使用无效的x值。有趣的是,这使得诸如x[foo]之类的表达式能够工作,因为它们被解释为*x+foo,这与*foo+x完全相同。foo的类型为int*。注意,这意味着foo可能指向一个int,或者数组中的多个int,或者根本不指向int。他们都是同一类型的。这对于理解foo非常重要[1]foo可以被看作是指向一个元素数组的第一个元素的指针。它类似于例如int数组[1];int*foo=&数组[0];。但是,C++没有对数组或指针进行任何类型的边界检查。因此,您可以轻松地访问超出边界的元素,如foo[1]。这将导致未定义的行为。但是ev
en当超出边界时,基类型仍然相同,因为数组中的每个元素都是相同的类型。如果foo被声明为指针类型,例如int*,则表达式foo[x]被解释为*foo+x。x的值是多少并不重要。foo+x可能指向有效的内存位置,也可能不指向。由您决定是否使用无效的x值。有趣的是,这使得诸如x[foo]之类的表达式能够工作,因为它们被解释为*x+foo,这与*foo+x完全相同。foo的类型为int*。注意,这意味着foo可能指向一个int,或者数组中的多个int,或者根本不指向int。他们都是同一类型的。这对于理解foo[1]很重要