一个朋友给我发了一段我不明白的片段。这是如何运作的?

A friend sent me a snippet I don't understand. How does this work?

感谢您的回复,每个人都对帮助我理解这是如何工作的很有帮助。

一个朋友发给我这段C代码问它是怎么工作的(他也不知道)。我通常不使用 C,但这激起了我的兴趣。我花了一些时间试图了解发生了什么,但最后我无法完全弄清楚。这是代码:

void knock_knock(char *s){
 while (*s++ != '[=10=]')
  printf("Bazinga\n");
}

int main() {
 int data[5] = { -1, -3, 256, -4, 0 };
 knock_knock((char *) data);
 return 0;
}

最初我认为这只是打印数组中数据的一种奇特方式(是的,我知道:\),但当我看到它没有时我很惊讶't print 'Bazinga' 5 次,但是 8 次。我搜索了一些东西并发现它正在使用指针(涉及到 c 时完全业余),但我仍然无法弄清楚为什么 8. 我搜索了一个多一点,发现通常指针在 C 中有 8 个字节的长度,我通过在循环之前打印 sizeof(s) 验证了这一点,果然它是 8。我以为就是这样,它只是在长度上迭代指针,所以它打印 Bazinga 8 次是有道理的。现在我也很清楚为什么他们会使用 Bazinga 作为要打印的字符串——数组中的数据只是为了分散注意力。所以我尝试向数组中添加更多数据,果然它一直打印 8 次。然后我更改了数组的第一个数字-1,以检查数据是否真的没有意义,这就是我感到困惑的地方。它不再打印 8 次,而只打印一次。阵列中的数据肯定不仅仅是一个诱饵,但对于我来说,我无法弄清楚发生了什么。

使用以下代码

#include<stdio.h>

void knock_knock(char *s)
{
    while (*s++ != '[=10=]')
        printf("Bazinga\n");
}

int main()
{
    int data[5] = { -1, -3, 256, -4, 0 };
    printf("%08X - %08X - %08X\n", data[0], data[1], data[2]);
    knock_knock((char *) data);
    return 0;
}

可以看到data数组的十六进制值为

FFFFFFFF - FFFFFFFD - 00000100

函数 knock_knock 打印 Bazinga 直到指向的值为 0x00 由于

while (*s++ != '[=12=]')

但是这里的指针指向字符,因此每个循环指向一个字节,因此,第一个 0x00 到达访问数组第三个值的 "first" 字节。

如果将十六进制数组输出为字符数组,很容易理解这里发生了什么。这里展示了如何做到这一点

#include <stdio.h>

int main(void) 
{
    int data[] = { -1, -3, 256, -4, 0 };
    const size_t N = sizeof( data ) / sizeof( *data );

    char *p = ( char * )data;

    for ( size_t i = 0; i < N * sizeof( int ); i++ ) 
    {
        printf( "%0X ", p[i] );
        if ( ( i + 1) % sizeof( int ) == 0 ) printf( "\n" );
    }

    return 0;
}

程序输出为

FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 
FFFFFFFD FFFFFFFF FFFFFFFF FFFFFFFF 
0 1 0 0 
FFFFFFFC FFFFFFFF FFFFFFFF FFFFFFFF 
0 0 0 0 

所以字符串 "Bazinga" 将被输出与数组中整数表示中的 non-zero 字节一样多的次数。正如所见,前两个负数在其表示中没有零字节。

然而数字256无论如何在其内部表示的最开始都有这样一个字节。因此,如果 sizeof( int ) 等于 4.

,则字符串将恰好输出八次

您需要查看整数数组中数据的字节表示 data。假设一个整数是 4 个字节,下面的表示给出了十六进制的数字

-1    -->  FF FF FF FF
-3    -->  FF FF FF FD
 256  -->  00 00 01 00
 -4   -->  FF FF FF FC
 0    -->  00 00 00 00

数组data就是这些以Little-Endian格式存储的数字。 IE。 LSbyte 排在第一位。所以,

data ={FF FF FF FF FD FF FF FF 00 01 00 00 FC FF FF FF 00 00 00 00};

函数 knock_knock 按字节遍历此数据并为每个 non-zero 打印 Bazinga。它在找到的第一个零处停止,这将在 8 个字节之后。

(注意:Integer 的大小可以为 2 或 8 个字节,但鉴于您的指针大小为 8 个字节,我猜测整数的大小为 4 个字节)。