C语言 一个朋友给我发了一个我不明白的片段,这是怎么工作的?

goqiplq2  于 2023-04-05  发布在  其他
关注(0)|答案(3)|浏览(151)

Thanks for the replies, everyone was useful in helping me understand how this works.

A friend sent me this piece of C code asking how it worked (he doesn't know either). I don't usually work with C, but this piqued my interest. I spent some time trying to understand what was going on but in the end I couldn't fully figure it out. Here's the code:

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

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

Initially I thought it was just a fancy way to print the data in the array (*yeah, I know :*), but then I was surprised when I saw it didn't print 'Bazinga' 5 times, but 8. I searched stuff up and figured out it was working with pointers (total amateur when it comes to c), but I still couldn't figure out why 8. I searched a bit more and found out that usually pointers have 8 bytes of length in C, and I verified that by printing sizeof(s) before the loop, and sure enough it was 8. I thought this was it, it was just iterating over the length of the pointer, so it would make sense that it printed Bazinga 8 times. It also was clea to me now why they'd use Bazinga as the string to print - the data in the array was meant to be just a distraction. So I tried adding more data to the array, and sure enough it kept printing 8 times. Then I changed the first number of the array, -1, to check whether the data truly was meaningless or not, and this is where I was confused. It didn't print 8 times anymore, but just once. Surely the data in the array wasn't just a decoy, but for the life of me I couldn't figure out what was going on.

b1uwtaje

b1uwtaje1#

使用以下代码

#include<stdio.h>

void knock_knock(char *s)
{
    while (*s++ != '\0')
        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数组的HEX值为

FFFFFFFF - FFFFFFFD - 00000100

函数knock_knock打印Bazinga,直到指向的值为0x00,因为

while (*s++ != '\0')

但是这里的指针指向的是字符,所以每个循环都指向一个字节,因此,第一个0x00访问数组第三个值的“第一个”字节。

xsuvu9jc

xsuvu9jc2#

您需要查看整数数组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格式存储的这些数字。即,LSbyte首先出现。因此,

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

函数knock_knock逐字节遍历这些数据,并为每个非零值打印Bazinga。它在找到第一个零时停止,这将在8个字节之后。
(Note:整数的大小可以是2或8个字节,但是考虑到你的指针大小是8个字节,我猜整数的大小是4个字节)。

fcg9iug3

fcg9iug33#

如果将十六进制的数组输出为字符数组,这里发生的情况很容易理解。

#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"将被输出的次数与数组中整数表示中的非零字节一样多。正如所看到的,前两个负数在其表示中没有零字节。
然而,在任何情况下,数字256在其内部表示的最开始都有这样一个字节。因此,只要sizeof( int )等于4,该字符串将被输出8次。

相关问题