Newbie trying to recode itoa here.
I am not quite sure about how the itoa function works, but here's how I want mine to work for now :
char *ft_itoa(int nb, char *str)
I want each digit of nb to be converted into a char which is to be put in *str.
Here's my code (I am not allowed to use any function but write that will only allow me to debug here.
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);
}
The program will segfault when trying to execute this line :
str[i] = y + '0';
If I had to take a wild guess, I would say it is because in my main
int main(void)
{
char *nbr = "1DF";
int nb = 479;
ft_itoa(nb, nbr);
return (0);
}
*nbr is not 'malloced'. I am not sure about how the allocation works when declaring char *nbr = "1DF";.
Thanks in advance for your help !
When compiling and linking C code, your compiler will store the various bits and pieces in different parts of the resulting executable file. These are known as 'sections', and depending on what is stored there, have different protection levels, usually enforced by the CPU virtual memory paging mechanism. For literal values (in this case
"1DF"), the compiler will store these in a section that is marked as read-only. Thus:declares a pointer variable (
nbr, stored on the stack), that points to"1DF", which is stored in a read-only section.For this reason, when you attempt to modify one of the characters of that string, the CPU will raise an error; the segmentation fault.
Solution
You can declare
nbras a pointer to a fixed length array ofchar(thus making the initial contents undefined and not stored in a read-only section) by changing the declaration to:The array is declared with a length of 4 to accommodate the trailing zero byte to indicate the end of the string.
Bonus Chatter
This will 'work', but there are a few things you should consider:
As noted, a string in C needs to be terminated with a zero byte (
'\0'in character notation) to be considered valid. Depending on the compiler, optimisation level, state of the computer, phase of the moon, etc, the array pointed to bynbrcould contain a zero byte in the appropriate place, but you should set it to avoid undefined behaviour.As the
strargument toft_itoais achar *, the length of the array pointed to bystris unknown insideft_itoa. A common idiom in C is to add an argument which is the length of the array so it can be safely worked with, and to change the return type to anintto allow indicating whether the operation succeeded or not (for example in the case where the string representation ofnbcan't fit in the array pointed to bystr). This would make the declaration offt_itoasomething likeint ft_itoa(int nb, char *str, int str_len)and the return could be0if failed,1if succeeded.In Depth
Looking over the executable created by compiling your code we have the following illustrative sections (many other sections have been omitted from the output):
.textis used to store the executable code portion (note theREADONLYandCODEflags).datais used to store global variables (note theDATAflag and absence of theREADONLYflag).rodatais used to store literal data (note theREADONLYandDATAflags)We can confirm that the
.rodatasection actually contains the literal string1DFwith: