当前位置: 首页 > 知识库问答 >
问题:

为什么sizeof运算符会为数组产生不同的结果

微生翼
2023-03-14

为什么sizeof运算符只应该是4个字节却生成12个字节?当我引用变量array时,这只是引用数组第一个索引的内存地址。实际上,我打印了第一个索引&array[0]的内存地址,并将其与array进行了比较,它们产生了相同的内存地址结果,这证实了它们都引用了数组的第一个索引,但是“array”产生了12个字节,而array[0]产生了4个字节。

int main() {
int array[] = {1,2,3};
int a = 1;
int b = sizeof(array); //this is referring to the first index of the array
int c = sizeof(array[0]); //this is also referring to the first index of the array

std::cout << b << std::endl;
std::cout << array << std::endl; //they have the same memory address
std::cout << &array[0] << std::endl; /* they have the same memory address, which confirms that array 
and &array[0] is the same */

return 0;
}

共有1个答案

双恩
2023-03-14

数组和指针是不同的,这是一个主要的例子。

在大多数上下文中,数组衰减为指向其第一个成员的指针。不发生这种衰减的少数几次之一是当数组是sizeof运算符的主题时。在这种情况下,它引用整个数组,表达式的计算结果为整个数组的大小(以字节为单位)。

C标准第6.3.2.1P3节对此进行了描述:

除非它是sizeof运算符、_alignof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为“array of type”的表达式将转换为类型为“Pointer to type”的表达式,该表达式指向数组对象的初始元素,而不是Lvalue。如果数组对象具有register storage类,则该行为未定义

以及第7.2节中的C++11标准:

类型为“N t的数组”或“t的未知界的数组”的lvalue或rvalue可以转换为类型为“指向t的指针”的prvalue。应用临时物化转换(7.4)。结果是指向数组第一个元素的指针。

和8.3.3p4:

LVALUE到RVALUE(7.1)、数组到指针(7.2)和函数到指针(7.3)标准转换不应用于sizeof的操作数。如果操作数是prvalue,则应用临时物化转换(7.4)。

所以我们实际拥有的是:

int b = sizeof(array);     // size of the entire array
int c = sizeof(array[0]);  // size of the first element of the array
int d = sizeof(&array[0]); // size of a pointer to an array element
 类似资料:
  • 问题内容: 在我的项目中,我的一个同事非常反对使用运算符,因为它“会产生大量开销”,这是什么原因呢?是真的吗 还有另一种方法可以检查对象的类型而不使用它? 因为我发现它在某些情况下非常有用。 问题答案: 确实产生一些开销,再加上后续的转换。使用最新版本的Java,开销已减少。但是无论如何,这都是微优化-也就是说,在一般情况下,您不必为此担心。 真正的反对意见是,在许多情况下,有更好的OOP方法可以

  • 我正在尝试编写一个Python实用程序,将Oracle的RAW字节字符串(作为字符串)转换为Guid,反之亦然。我试图重用我在C#中构建的同一个实用程序中的算法,但是从同一个字节数组构造一个和一个会产生不同的Guid/UUID。它们是一样的,不是吗?我读过UUID只是一个更好的术语。 在C#中,我有一个字节数组,< code>byte_array如下所示: 在 Python 中,我有一个字节数组,

  • 问题内容: 我有一个Python程序,其中两个变量被设置为值’public’。在条件表达式中,比较var1是var2,但如果将其更改为var1==var2,则返回True。 现在,如果我打开Python解释器并进行相同的比较,则此操作成功。 我错在哪里? 问题答案: 1481 是身份测试,是平等测试。你的代码中发生的情况将在解释器中进行模拟,如下所示: 所以,难怪他们不一样吧? 换句话说:

  • 问题内容: 为什么需要添加“ L”字母以获得正确的长值?还有什么其他价值呢? 问题答案: 你的第一个值实际上是一个long(因为是,并且是,所以带值的值的结果就是一个long值。 但是第二个值是一个整数(因为你仅将一个值与一个值混用。所以结果将是一个整数。现在,所获得的结果超出了整数的实际范围。因此,在分配给该变量之前,被截断以适合有效的整数范围。 查看以下打印语句: 当你运行上面的代码时: 输出

  • 但令我惊讶的是,只有带有或的代码会被gcc转换为单个64位比较。为什么?(https://godbolt.org/z/ap1ocs) 对优化器来说,如果我在四个字节的连续对上检查相等性,这与在所有八个字节上进行比较是一样的,难道不是很明显吗? 避免将两个部分单独进行布尔化的尝试会更有效地编译(少了一个指令,没有对EDX的错误依赖),但仍然有两个单独的32位操作。 GCC和Clang在通过值传递结构

  • 以下代码在C 14中被认为是非法的,但在C 17中是合法的: 不要费心测试它,你会得到不一致的结果,很难确定这是一个错误还是故意的行为。但是,比较两个草案(N4140 vs N4527,都可以在github.com/cplusplus/draft上找到),[func.wrap.func.inv]有一个显著的区别。第2段: 返回:如果R为空,则无,否则返回值INVOKE(f, std::forwar