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

问题描述 投票:0回答:3

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

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

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;
}

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

c pointers ascii overflow ansi-c
3个回答
7
投票

使用以下代码

#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
到达访问数组第三个值的“第一个”字节。


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
按字节遍历此数据并为每个非零打印
Bazinga
。它在找到的第一个零处停止,这将在 8 个字节之后。

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


1
投票

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

#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
.

,则字符串将精确输出八次
© www.soinside.com 2019 - 2024. All rights reserved.