英文:
Unexpected behavior of memset in C++
问题
我注意到在使用动态数组时,memset()
函数的行为与预期不符。
// 这个例子运行良好,将每个索引的值设置为0
int dp[5];
memset(dp, 0, sizeof(dp));
// 这个例子不如预期,某些索引处存在垃圾值
int *dp = new int[5];
memset(dp, 0, sizeof(dp));
// 而这个例子按预期运行
int *dp = new int[5];
memset(dp, 0, sizeof(dp[0]) * n);
是什么导致了这种不符合预期的行为?
编辑:
我理解sizeof(dp)
返回指针的大小,而sizeof(dp[0])
返回dp[0]
的大小。我的主要关注点是,如果第一个示例在使用指针大小,即sizeof(dp)
时能够正常工作,那么为什么第二个示例不能以类似的方式工作?为什么会出现垃圾值?
英文:
I have noticed unexpected behavior of memset()
when used with dynamic arrays.
// This works well, sets value of each index = 0
int dp[5];
memset(dp, 0, sizeof(dp));
// This one doesn't work as expected, there are garbage values at some indexes
int *dp = new int[5];
memset(dp, 0, sizeof(dp));
// And this one works as expected
int *dp = new int[5];
memset(dp, 0, sizeof(dp[0]) * n);
What defines the reason for this unexpected behavior?
EDIT:
I understand that sizeof(dp)
gives the size of pointer where as sizeof(dp[0])
gives the size of dp[0]
. My main concern is if first one is working fine with the pointer size i.e. sizeof(dp)
then why isn't the second one working similarly, why are there garbage values?
答案1
得分: 4
这
int dp[5];
声明`dp`为一个包含5个整数的数组,一个`int[5]`。在这里,`dp` **不是** 指针。它是一个数组。数组不是指针。`sizeof dp` 是 `5 * sizeof int`。
---
另一方面,这个:
int* dp = ... whatever ...;
声明`dp`为一个指向`int`的指针,一个`int*`。`sizeof dp` 是一个`int*`的大小。
重要提示:指针不是数组,数组也不是指针。这里的`dp`与上面的`dp`非常不同。在这里,`dp`是指向单个`int`的指针,指向动态分配数组的第一个元素。
---
当`dp`是一个指针时,`dp[0]`等同于`*(dp + 0)`,因此`5 * sizeof dp[0]`是当`dp`指向包含`5`个整数的数组的第一个元素时,数组的总大小。
---
考虑这个:
#include <iostream>
int main() {
std::cout << sizeof(int) << "\n";
std::cout << sizeof(int*) << "\n";
std::cout << sizeof(int[5]) << "\n";
}
[可能的输出是](https://godbolt.org/z/ehKKanx4e):
4
8
20
这里整数的大小是4,而指向整数的指针的大小是8。这些数字可以不同,但5个整数的数组的大小始终是`5 * sizeof(int)`,通常`sizeof(int*)`远小于`sizeof(int[5])`。
---
关于你的编辑...
> 我的主要关注点是第一个使用指针大小的是否正常工作,为什么第二个不以类似的方式工作,为什么有垃圾值?
请参考上面的解释。在第一个示例中,`dp` **不是** 指针。当你声明`dp`为`int dp[5];`时,`dp` **不是** 指针。它是一个数组。另一方面,`int* dp = ...` 声明`dp`为指向整数的指针。
---
PS:使用向量而不是手动管理的C数组,并跳过使用 `memset`:
std::vector<int> x(5);
std::cout << "元素数量:" << x.size();
英文:
This
int dp[5];
declares dp
as an array of 5 integers, a int[5]
. Here dp
is not a pointer. It is an array. Arrays are not pointers. The sizeof dp
is 5 * sizeof int
.
On the other hand, this:
int* dp = ... whatever ...;
declares dp
as a pointer to int
, a int*
. The sizeof dp
is that of a int*
.
Important: Pointers are not arrays and arrays are not pointers. The dp
here is very different to the dp
above. Here dp
is a pointer to a single int
, the first element of the dynamically allocated array.
When dp
is a pointer, then dp[0]
is equivalent to *(dp + 0)
, hence 5 * sizeof dp[0]
is the total size of the array when dp
points to the first element of an array with 5
integers.
Consider this:
#include <iostream>
int main() {
std::cout << sizeof(int) << "\n";
std::cout << sizeof(int*) << "\n";
std::cout << sizeof(int[5]) << "\n";
}
4
8
20
Here the size of a integer is 4 while the size of a pointer to integer is 8. Those numbers can differ, but the size of an array of 5 integers is always 5 * sizeof(int)
and typically sizeof(int*)
is much smaller than sizeof(int[5])
.
About your edit...
> My main concern is if first one is working fine with the pointer size i.e. sizeof(dp) then why isn't the second one working similarly, why are there garbage values?
See above. In the first example dp
is not a pointer. When you declare dp
as int dp[5];
then dp
is not a pointer. It is an array. Arrays are not pointers. int* dp = ...
on the other hand declares dp
as a pointer to integer.
PS: Use a vector instead of manually managed c-arrays and skip the usage of memset
:
std::vector<int> x(5);
std::cout << "number of elements: " << x.size();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论