2011-08-26 69 views
41

是不是可以在整数数组上使用memset?我尝试了下面的memset调用,并没有在int数组中得到正确的整数值。为什么“memset(arr,-1,sizeof(arr)/ sizeof(int))”不能将整数数组清除为-1?

int arr[5]; 
memset (arr, -1, sizeof(arr)/sizeof(int)); 

Vaules我是:

arr[0] = -1 
arr[1] = 255 
arr[2] = 0 
arr[3] = 0 
arr[4] = 0 
+1

可能更容易做到这一点:int arr [5] = {-1}; –

+24

@Tom Dignan:除了仅将第一个元素初始化为-1,其余所有元素初始化为0. – tinman

回答

69

只是改变memset (arr, -1, sizeof(arr));

注意,对于其它的值大于0和-1这是行不通的,因为memset字节值的记忆开始于由*ptr以下指示的可变块num字节。

void * memset (void * ptr, int value, size_t num); 

而且,由于int是在超过一个字节表示,你不会得到你的数组中的整数期望值。

例外:

  • 0是因为一个例外,如果你设置所有字节为0,则该值将是零
  • -1是因为另一个例外,因为帕特里克强调-1在0xFF的中int8_t(= 255),并为0xffffffff在int32_t

你有原因:

arr[0] = -1 
arr[1] = 255 
arr[2] = 0 
arr[3] = 0 
arr[4] = 0 

是因为,在你的情况下,一个int的长度是4个字节(32位表示),你的数组的长度是20(= 5 * 4),你只设置5个字节为-1 = 255)而不是20.

+5

那么,在这种特殊情况下(对于-1来说,memset实际上是可行的)。因为int8_t中的-1是0xff,int32_t中的0xffffffff等等。 IOW:memset对0和-1工作正常,但对于其他所有情况不是很有用。 –

+0

你是对的Patrick,谢谢..我相应地改变了我的回答 –

+6

@Patrick B.:它可以在许多平台上正常工作,但不是全部。并非所有的平台都使用二进制补码,并且您也可以通过使用memset来初始化一个int来触发陷阱表示。 –

5

为什么划分的?

memset(arr, -1, sizeof(arr)); 

你的版本,sizeof(arr)/sizeof(int),为您提供了数组中元素的个数。

+3

请注意,memset()会在寻址的位置设置_bytes_的值,而不是多少“项目”。你希望将5个字节的字节值设置为'-1'。这样做恰好将格式值设置为“-1”。 –

+1

@Jeff:的确,巧合,因为-1的int通常是$ FFFFFFFF(假设32位int和2的补码),而-1的字节是$ FF。如果他选择-2($ FE),它将变成$ FEFEFEFE,这是一个-16843010的整数。 –

30

不要使用memset来初始化除单字节数据类型以外的任何内容。

乍一看,它可能会出现,它应该用于初始化int0-1(和在许多系统上,将工作)工作,但此时你没有考虑到,你可能会生成陷阱的可能性表示,导致未定义的行为,或整数表示为not necessarily two's complement的事实。

将数组int初始化为-1的正确方法是遍历数组,并显式设置每个值。

+8

我认为这个答案应该考虑一个条款,如“如果你想写绝对可移植的代码**”,不要使用memset()'... **。大多数人既不写也不打算写便携式代码。当它适用于两种架构时,大多数人称代码为“便携式”。 “正确的方式......”中的“正确”一词也可以更改为“便携式”。如果您不想编写绝对可移植的代码,那么它不会更正确。 –

+0

+1 // @Complicatedseebio不能同意更多,很多程序员用'正确'和'stl this'来跳下人们的喉咙。他们经常看到具体问题需要什么。 –

+7

@Comlicated see bio @Adam:但是,使用循环初始化一个'int'数组可以保证在所有情况下都能正常工作,而使用memset可能无法正确执行它(或者可能会出现更糟糕的情况)。如果您熟悉代码运行的平台,并且知道它不会导致问题,我不会说您不能使用memset。但是我不了解每个可能阅读这个答案的人的平台,所以我更喜欢安全地玩。我希望能够平衡我在答案中使用的某些“极端”(出于理由)。 –

4

您可以通过直接初始化数组保存自己一些打字:

int arr[5] = {-1, -1, -1, -1, -1}; 

这条线比memset的短,它也适用。

+0

数组初始值设定为+1,虽然它仅适用于少数值。 –

9

GCC提供了一个很好的数组初始化的快捷

int arr[32] = {[0 ... 10] = 3, [11 ... 31] = 4}

心灵的空间之前和之后...

1
void * memset (void * ptr, int value, size_t num); 

当应用于设置字符数组此功能以及在大多数系统上。 它将ptr指向的内存块的第一个数字BYTES设置为指定的值(解释为无符号字符)。 memset-C++ Reference 它每次运行一个字节。因此,如果您为int值不超过0xff的第二个参数赋值,那么它工作正常。

至于你的版本,第三个参数是数组元素的数量,所以你得到了你的输出。 事实上,事实是,你应该分配第三个参数你想要的字节数。 所以正确的版本应该是这样的:

memset (arr, -1, sizeof(arr)); 
相关问题