11

我正在阅读这个例子

真正的“Hello World!” 为 CUDA!
什么\0

char str[16] = "Hello \0\0\0\0\0\0";

代表?

我不确定为什么里面有 16 个字符str"Hello "然后全为零(这不是全局变量)。我怎么能确定它只包含零?”

4

3 回答 3

24

'\0'ASCII NUL 空字符(ASCII 代码零)。

指定数组中的所有零字节是没有意义的。以下是等价的:

char str[16] = "Hello \0\0\0\0\0\0";
char str[16] = "Hello ";

如果数组已部分初始化,则未初始化的元素将接收到相应类型的值 0。[IBM]

由于长度被指定为 16,编译器将自动确保数组的其余部分(之后"Hello "为零)。作者这样做是为了“确保”数组的其余部分为零,或者作为读者。

与我们最初的分析相反,CUDA 内核并没有“插入字节”来附加World!到现有字符串。 Hello首先打印。然后内核将字符串修改为World!,最终打印出来。

字符串被指定为 16 字节的唯一原因是因为这是内核设计使用的块大小,并且他们必须确保内核不会弄乱不应该的内存。

我在(部分)原始代码中添加了一些注释,以使这一切更加清晰:

__global__                              // The kernel which is run in parallel
void hello(char *a, int *b) 
{
    a[threadIdx.x] += b[threadIdx.x];
}

int main()
{
    // The line in question. There's really no point in padding it with zeros.
    // The zeros are *not* replaced, and only 12+1 bytes are being specified.
    char a[N] = "Hello \0\0\0\0\0\0";

    // These values are added (by the CUDA kernel) to the array above. Again,
    // since partial arrays are zero-filled, there's no point in filling this in.
    int b[N] = {15, 10, 6,  0, -11,  1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

    // 'H' + 15 = 'W'
    // 'e' + 10 = 'o'
    // 'l' + 6  = 'r'
    // 'l' + 0  = 'l'
    // 'o' - 11 = 'd'
    // ' ' + 1  = '!'

    char *ad;
    int *bd;
    const int csize = N*sizeof(char);
    const int isize = N*sizeof(int);

    printf("%s", a);                  // Print "Hello "

    cudaMalloc( (void**)&ad, csize ); 
    cudaMalloc( (void**)&bd, isize ); 
    cudaMemcpy( ad, a, csize, cudaMemcpyHostToDevice ); 
    cudaMemcpy( bd, b, isize, cudaMemcpyHostToDevice ); 

    dim3 dimBlock( blocksize, 1 );
    dim3 dimGrid( 1, 1 );
    hello<<<dimGrid, dimBlock>>>(ad, bd);   // Add the values in b to a


    cudaMemcpy( a, ad, csize, cudaMemcpyDeviceToHost ); 
    cudaFree( ad );
    cudaFree( bd );

    printf("%s\n", a);               // print "World!"
    return EXIT_SUCCESS;
}
于 2013-06-17T07:42:35.847 回答
6

\0代表NUL, Nul 用作字符串终止字符。这意味着它说明了字符串的结尾。NUL 字节的值是0x00

于 2013-06-17T07:34:32.913 回答
2

如前所述,它没有什么意义。\0只是将带有代码 0 的字符放在那里,但无论如何都会发生。这样做的好处是没有给出数组边界,因为额外的 0 将计入,或者在 0 之后有更多字符。

char foo_and_bar[] = "Foo\0Bar";

将用 0 分隔部分。

于 2013-06-17T07:36:51.433 回答