一个朋友给我发了一段我不明白的片段。这是如何运作的?
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 个字节)。
感谢您的回复,每个人都对帮助我理解这是如何工作的很有帮助。
一个朋友发给我这段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 个字节)。