C++ toString (char*) implmentation

Programming, for all ages and all languages.
Post Reply
RadPoseidon
Posts: 8
Joined: Tue Oct 26, 2021 8:21 pm

C++ toString (char*) implmentation

Post by RadPoseidon »

I'm trying to write a function to convert an int to a string for my basic kernel. This is my current implementation:

Code: Select all

const char* toString(int i) {
	unsigned int it = 0;
	char *str;

	// TODO: Fix for negative numbers

	while(i > 0) {
		int n = i % 10;
		str[it] = (char)('0' + n);
		i = i / 10;
		it++;
	}

	return str; // This is line 155
}
However, C++ gives me the warning kernel/kernel.cpp:155:16: warning: 'str' is used uninitialized. I can't figure out what to initialize str to, as initializing it to "" also causes a warning, and ignoring the warning causes the test value of 53 appear as "S ".

Edit: I think that the "S " comes from it reading from a point in memory.
User avatar
Assembler
Member
Member
Posts: 30
Joined: Fri Oct 27, 2006 5:26 am
Contact:

Re: C++ toString (char*) implmentation

Post by Assembler »

Hello RadPoseidon,

The warning is obvious, you're using 'str' without initializing it which should cause a segmentation fault if you run it. You need to either allocate some memory in your 'toString' function or pass it to it.

Code: Select all

char *str = new char[10]; // you probably won't need more that 10 characters.
or
char *str = (char *)malloc(10 * sizeof(char));
Also note that:

Code: Select all

char str[10] won't work because it will be allocated onto the stack of 'toString' which will be destroyed when 'toString' returns.
Finally, your code doesn't exactly do what you're hoping for, indeed it will convert an int value to an array of characters but the array is in reverse order.

Hope that helped.
Systems and Computer Engineering Researcher
"Do you pine for the nice days of Minix-1.1, when men were men and wrote their own device drivers?" -- Linus Torvalds
http://sce.carleton.ca/~maslan
RadPoseidon
Posts: 8
Joined: Tue Oct 26, 2021 8:21 pm

Re: C++ toString (char*) implmentation

Post by RadPoseidon »

Thank you, I felt it had something to do with memory allocation, but I wasn't sure what to do. I had also conveniently written a function to get the digits in an int shortly beforehand.
I'm getting the error in function `_Z8toStringi': kernel.cpp:(.text+0x514): undefined reference to `_Znam' on link now, but I think it's unrelated to this and more due to a prior implementation of something.
Octocontrabass
Member
Member
Posts: 5512
Joined: Mon Mar 25, 2013 7:01 pm

Re: C++ toString (char*) implmentation

Post by Octocontrabass »

That error means the linker can't find your implementation of "operator new[](unsigned long)". (Or perhaps you haven't implemented it yet?)

You can use c++filt or various websites to demangle symbol names.
nullplan
Member
Member
Posts: 1766
Joined: Wed Aug 30, 2017 8:24 am

Re: C++ toString (char*) implmentation

Post by nullplan »

As to your original question, in most cases it is simpler to have the caller provide a buffer. Taking care of the whole domain, a simple implementation might be:

Code: Select all

void toString(int i, char *s) {
  static_assert(-5 % 3 == -2, "Compiler uses symmetric modulo"); /* if this fails, the code below won't work. */
  if (i < 0)
    *s++ = '-';
  else
    i = -i;
  int t = i;
  do s++;
  while (t /= 10);
  *s = 0;
  do *--s = '0' - i % 10;
  while (i /= 10);
}
This always turns the argument negative, because while each positive int can be turned negative, the reverse is not true (INT_MIN cannot be turned positive on most systems). Then it is simply a matter of working with division in the negative numbers. I put an assert in to verify that symmetric modulo is used, but it is used by pretty much all implementations I have ever come across. The alternative would not be pretty. In the case of absolute modulo, you get the inverse of each digit except 0, and the divisions would raise the argument towards -1, unless the argument was 0 from the start.

Now, there are some obvious areas for improvement, still. The buffer is unbounded at the moment, so the caller needs some way of knowing how to allocate enough memory from the start. Or alternatively, the caller could provide a buffer size, but then you need to specify what happens when the buffer runs out. I shall leave that as exercise for the reader.
Carpe diem!
RadPoseidon
Posts: 8
Joined: Tue Oct 26, 2021 8:21 pm

Re: C++ toString (char*) implmentation

Post by RadPoseidon »

Yeah, I missed an article that explained defining new/delete, etc. I thought I had objects working since it let me construct and use a test object.
Post Reply