为什么这个C代码进入循环? #包括 #包括 int p() { 字符数据[7]=“你好!\0”; uint64_t*ptr=((uint64_t)数据+0x18); printf(“%s”,数据); (*ptr)-=10; 返回0x00; } int main(int argc,字符**argv) { p(); }

为什么这个C代码进入循环? #包括 #包括 int p() { 字符数据[7]=“你好!\0”; uint64_t*ptr=((uint64_t)数据+0x18); printf(“%s”,数据); (*ptr)-=10; 返回0x00; } int main(int argc,字符**argv) { p(); },c,C,您拥有的是未定义的行为 #include <stdio.h> #include <stdint.h> int p() { char data[7]="Hello!\0"; uint64_t *ptr=((uint64_t)data + 0x18); printf("%s",data); (*ptr)-=10; return 0x00; } int main(int argc,char **argv) { p(); } 在

您拥有的是未定义的行为

#include <stdio.h>
#include <stdint.h>
int p()
{
    char data[7]="Hello!\0";
    uint64_t *ptr=((uint64_t)data + 0x18);
    printf("%s",data);
    (*ptr)-=10;
    return 0x00;
}

int main(int argc,char **argv)
{
    p();
}
在绑定外写入数组会导致未定义的行为。这不是空终止字符串的正确方法。您可以选择以下选项之一

换成

char data[7]="Hello!\0";
你甚至可以

char data[7]="Hello!";
编辑:

通过这样做

char data[]="Hello!";
您正在使指针指向某个未分配的内存位置。稍后您将尝试写入此位置

uint64_t *ptr=((uint64_t)data + 0x18);

因此,访问绑定外的数组或写入未分配的内存会导致未定义的行为。您需要首先修复它们,如其他答案和注释中所述写入字符数据[7]=“Hello!\0”可能是个问题,但我不认为这是问题的唯一来源

我的猜测是:
uint64_t*ptr=((uint64_t)数据+0x18)

(*ptr)-=10

通过这样做,您可能正在修改堆栈中的返回地址或执行类似操作。

什么循环?你是说它永远挂着?你有两个问题,都会导致。实际上,它们都是相同的问题,但用两种不同的方式表达。问题是您在两个位置写入了
数据
数组的边界之外。我猜代码是在修改堆栈以改变返回地址,从而导致无限循环(跳转到自身)。然而,程序实现这一点的方式是通过错误行为和错误使用未定义的行为,它只能在一些有限的系统上工作。我只是指出,在声明这样的字符数组时,不需要放入
\0
\0
自动放置在字符串的末尾,我通常不建议使用字符串初始化字符数组的长度(如果不是为了避免使用0终止符)。例如,
char数据[6]=“你好!”编译,但不0-终止。显式
\0
可防止该错误。在这种情况下,省略这两个选项,显式长度和
\0
更好。但是,如果出于某种原因,您坚持使用显式长度,那么显式
\0
在我看来是一件好事,甚至更好,请将其留给编译器,
char data[]=“Hello!”@SouravGhosh是的,我接受。你能解释一下这个数组是如何越界的吗@RajatVerma字符串literal
“Hello!\0”
是一个指向常量字符数组的指针,该数组包含
'H'
'e'
'l'
'o'
!'
'\0'
'\0'
。将显式
“\0”
添加到字符串中并不会结束字符串,它只会向字符串中添加另一个字符。@JoachimPileborg:仅当有空间容纳另一个0-终止符时。见上文。
(*ptr)-=10;