在C++中memset的意外行为

huangapple go评论85阅读模式
英文:

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";
}

Possible output is:

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();

huangapple
  • 本文由 发表于 2023年6月16日 01:05:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76483974.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定