2014-10-01 85 views
-4

问题,假设我有:填充字符数组的好奇心

int main(void) 
{ 
    char str[32]; 
    for (i = 0; i < 32; i++) 
     str[i] = 0; 
} 

,但我想这样做4倍快

int main(void) 
{ 
    char str[32]; 
    for (i = 0; i < 32/4; i += 4) 
     str[i] = (int)0; 
} 

我想到的是,整个阵列将用零填充。 但阵列没有被零填充

我的问题:为什么数组没有被零填充?如何填充每个int块的数组?我的问题是Research for c功能,如何告诉编译器 - 写4个字节的块,即整数寄存器,它会减少内存访问次数4次,在x64处理器上减少8次

感谢大家,如下做工精良:

int main(int argc, char *argv[]) 
{ 
     char str[32]; 
     int i; 
     for (i = 0; i < 32; i++) 
       str[i] = 12; 
     for (i = 0; i < 32/sizeof(int); i++) 
       ((int *) str)[i] = 0; 
     printf("%d\n", i); 
     for (i = 0; i < 32; i++) 
       printf("%d\n", str[i]); 
     return 0; 
} 
+2

“0”本身的类型是“int”,“(int)0”与“0”没有区别。 – 2014-10-01 15:33:04

+0

你的意思是快4倍?你所做的每次循环跳过3个块 – Grice 2014-10-01 15:34:00

+0

这是一个堆栈变量,所以编写'char str [32] = {'\ 0'};'会初始化整个块 – 2014-10-01 15:42:42

回答

-2

你要转换指针与int,不是值:

int main(void) 
{ 
    char str[32]; 
    for (i = 0; i < 32/sizeof(int); i++) 
     ((int *) str)[i] = 0xAABBCCDD; //Be careful of Endianness 
} 

或者:

int i; 

union block_fill 
{ 
    char arr[24]; 
    int iarr[6]; 
}; 

union block_fill block_arr; 

for(i=0; i<6; i++) 
    block_arr.iarr[i] = 0x11223344; 

for(i=0; i<24; i++) 
    printf("%x", block_arr.arr[i]); 
+1

而'i'应该只增加1. – potrzebie 2014-10-01 15:42:28

+0

在你的例子中,你有很多**未定义的行为。 – 2501 2014-10-01 15:44:21

+1

建立在@potrzebie上,上限应该是32 /(sizeof int)'否则你将会跑出界限。 – 2014-10-01 15:45:07

4

正确的和最快的方法是数组初始化为零

char str[32] = { 0 } ; 

如果要设置数组到零之后,然后用memset的,使编译器优化和内在功能,编译器会找出最快的方法来清零数组。

memset(str , 0 , sizeof(str)) ; 
+0

是的,当然,但我的问题是研究c功能 如何告诉编译器 - 写入4个字节的块,即整数寄存器,它会减少4倍的内存访问次数,在x64处理器上减少8倍 – 2014-10-01 15:43:40

+1

@IvanIvanovich:谁会说int会是4个字节?该标准将int定义为至少16位大小。 2个字节或更多...... – 2014-10-01 15:48:55

+0

在x32和x64机器上int是32位,即4个字节。 chort是16位 – 2014-10-01 15:54:44

1

正如指出的那样@ user2501,初始化为{0}或使用memset是最快的和正确的方法。

如果您想使用类似((int *)str)[i] = 0的东西,请不要这样做,这会导致未对齐的访问。

作为替代memset,在C99(并假设int是4个字节)可以使用工会的类型双关特征:

#include <stdio.h> 

typedef union { 
    char as_string[32]; 
    int as_int[8]; 
} foo; 

int main(void) 
{ 
    foo x; 
    int i; 

    for (i = 0; i < 8; i++) 
     x.as_int[i] = 0; 
    for (i = 0; i < 32; i++) 
     printf("%d", x.as_string[i]); 
    printf("\n"); 
    return 0; 
} 

输出:

00000000000000000000000000000000 
0

看来你被迫使用指针和强制转换,该版本使用堆以便在正确对齐int的地址上分配str

#include <stdio.h> 
#include <stdlib.h> /* malloc, free */ 
#include <stdint.h> /* intptr_t (pointer arithmetic using modulo division) */ 

#define MAX 32 

int main(void) 
{ 
    size_t i, align; 
    char *ptr, *str; 

    align = __alignof__(int); 
    ptr = malloc(MAX + align);     /* MAX + max align distance */ 
    str = ptr + align - (intptr_t)ptr % align; /* now str is properly aligned */ 
    for (i = 0; i < MAX/sizeof(int); i++) 
     ((int *)str)[i] = 0; 
    for (i = 0; i < MAX; i++) 
     printf("%d\n", str[i]); 
    free(ptr); 
    return 0; 
} 

注意__alignof__gcc扩展,如果你是Visual Studio_Alignof下,如果你是舒服C11更改为__alignof