1

新手试图在itoa这里重新编码。我不太确定 itoa 函数是如何工作的,但这是我现在希望我的工作方式: char *ft_itoa(int nb, char *str) 我希望将 的每个数字nb转换为要放入的字符*str。这是我的代码(我不允许使用任何功能,但这write只会让我在这里调试。

char    *ft_itoa(int nb, char *str)
{
    int i;
    int y;
    int nbinit;
    int neg;

    i = 0;
    y = 0;
    nbinit = nb;
    neg = 0;
    if(nb < 0)
    {
        nb = -nb;
        neg = 1;
        str[i] = '-';
        i++;
    }
    while(nb / 10 > 0)
    {
        i++;
        nb = nb / 10;
    }
    if(neg == 1)
        nb = -nbinit;
    else
        nb = nbinit;
    while(nb / 10 > 0)
    {
        y = nb % 10;
        str[i] = y + '0';
        i--;
        nb = nb / 10;
    }
    str[i] = nb + '0';

    return (str);
}

尝试执行此行时,程序将出现段错误: str[i] = y + '0';

如果我不得不大胆猜测,我会说这是因为在我的主要

int     main(void)
{   
    char *nbr = "1DF";
    int nb = 479;
    ft_itoa(nb, nbr);
    return (0);
}

*nbr不是“分配的”。我不确定声明时分配是如何工作的 char *nbr = "1DF";

在此先感谢您的帮助 !

4

1 回答 1

1

编译和链接 C 代码时,您的编译器会将各种位和片段存储在生成的可执行文件的不同部分中。这些被称为“部分”,根据存储在那里的内容,具有不同的保护级别,通常由 CPU 虚拟内存分页机制强制执行。对于文字值(在这种情况下"1DF"),编译器会将它们存储在标记为只读的部分中。因此:

char *nbr = "1DF";

声明一个指针变量(nbr,存储在堆栈中),指向"1DF",存储在只读部分中。

因此,当您尝试修改该字符串的某个字符时,CPU 将引发错误;分段错误。

解决方案

您可以通过将nbr声明char更改为:

char nbr[4];

该数组被声明为长度为 4 以容纳尾随零字节以指示字符串的结尾。

奖金喋喋不休

这将“有效”,但您应该考虑以下几点:

  • 如前所述,C 中的字符串需要以零字节('\0'以字符表示法)终止才能被视为有效。根据编译器、优化级别、计算机状态、月相等,指向的数组nbr可能在适当的位置包含零字节,但您应该设置它以避免未定义的行为。

  • 由于 的str参数ft_itoa是 a char *,所以 指向的数组的长度在str内部是未知的ft_itoa。C 中的一个常见习惯用法是添加一个参数,该参数是数组的长度,以便可以安全地使用它,并将返回类型更改为 anint以允许指示操作是否成功(例如,在的字符串表示nb不适合 ) 指向的数组str。这将声明ft_itoa类似的东西,如果失败则int ft_itoa(int nb, char *str, int str_len)返回,如果成功。01

深入

查看通过编译代码创建的可执行文件,我们有以下说明性部分(输出中省略了许多其他部分):

$ objdump --section-headers

a.out:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn

...

 12 .text         00000324  000102e0  000102e0  000002e0  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

...

 14 .rodata       00000008  0001060c  0001060c  0000060c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

...

 21 .data         00000008  0002101c  0002101c  0000101c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
...
  • .text用于存储可执行代码部分(注意READONLYCODE标志)
  • .data用于存储全局变量(注意DATAflag和flag的缺失READONLY
  • .rodata用于存储文字数据(注意READONLYDATA标志)

我们可以确认该.rodata部分实际上包含文字字符串1DF

$ objdump --full-contents --section .rodata

a.out:     file format elf32-littlearm

Contents of section .rodata:
 1060c 01000200 31444600                    ....1DF.
于 2021-02-21T03:52:47.987 回答