When I use itoa() it needs a char* _DstBuff, what is the best practice here?
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int num = 100;
// I'm sure here is no memory leak, but it needs to know the length.
char a[10];
// will this causue memory leak? if yes, how to avoid it?
// And why can itoa(num, b, 10); be excuted correctly since b
// has only allocated one char.
char *b = new char;
// What is the difference between char *c and char *b
// both can be used correctly in the itoa() function
char *c = new char[10];
itoa(num, a, 10);
itoa(num, b, 10);
itoa(num, c, 10);
cout << a << endl;
cout << b << endl;
cout << c << endl;
return 0;
}
the output is:
100
100
100
So could anyone explain the differenct between char *b = new char; and char *c = new char[10]; here?
I know char *c will dynamiclly allocate 10 chars, but that means char *b will only dynamically allocate 1 char, if I'm right about this, why is the output all correct?
actually which is the best practice of a, b, or c?
Best practice: Don't use it at all.
Why? Because it's not in the standard.
What should I do instead? Use std::to_string.
(If you're really stuck having to use itoa, then use a large local static buffer, like char[512] or so -- if you want to be really really safe you can make the array size sizeof(unsigned long long int) * CHAR_BIT + 2 or something like that so it can always hold any number expressed in any base, plus sign.)
In this question I posed, you'll find a dozen efficient functions for converting an integer into a string, all of which allocate and return a std::string so you needn't worry about buffer overflow. And several options in there are blistering fast.
What you are describing is not a memory leak, but rather a buffer overflow.
Basically, you are getting lucky. If you allocate only one character, but then write four characters to it, you are overrunning what has been allocated to you, and this is a bug.
cout << b << endl; : is incorrect, it is a buffer overflow.
because you allocate 1 byte of memory to contain one char. but, you write on it with itoa() 10+1chars.
so you have to allocate : char * d = new char[11]; // 10 chars + '\0'(end of string char).
then use itoa(num , d , 10);
in addition itoa() is non standard, so i prefer to use the standard sprintf(d,"%d",num);
and as said in the comment below, if you dont need char* and you can use std::string. use
string d = std::to_string(num);
Related
I am trying to pick up my C++; I have basic understanding of pointers and references; but when it comes to char pointer to array, it seems nothing works for me.
I have a small piece of codes here (omitted include and namespace statements), I have included my questions as comments below:
I have gone through at least 5 other questions on SO to try to understand it; but those answers didn't the answer I expected and to the extent that could help understand the actual issue there.
Could you kindly explain the problems I commented below with a bit of depth from the surface (so please don't dive into it directly)?
int main(){
// 1 this is a char pointer to a char;
char * c = new char;
*c ='A';
cout << c << endl; // this gives me memory address;
cout << *c << endl;// this gives me the value in the memory address;
// 2 this is a char array initialised to value "world";
char d[6] = "world";
cout << d[0] << endl; // this gives me the first element of char array;
// 3 this is char pointer to char array (or array of char pointers)?
char * str = new char[6];
for(int i=0;i<6;i++){ //
str[i]=d[i]; // are we assigning the memory address (not value) of respective elements here?
} // can I just do: *str = "world"; what's the difference between initialising with value
// and declaring the pointer and then assign value?
char * strr = "morning";
char b[6] = "hello";
cout << b << endl;
cout << (*str)[i] << endl; // why? error: subscripts requires array or pointer type
cout << str[1] << endl;
cout << (*strr)[1] << endl; // why? error: subscripts requires array or pointer type
}
// 1 this is a char pointer to a char;
Right.
// 2 this is a char array initialised to value "world";
Right, "world\0" is created by the compiler and is put in the read-only memory area of the program. Note that this is called a string literal. Then the string is copied over to the char array d.
// 3 this is char pointer to char array (or array of char pointers)?
That's a char pointer yes, a pointer to a single char.
// are we assigning the memory address (not value) of respective
elements here?
No, you're assigning the values of the elements. This is allowed because str[i] is the same as *(str + i) so you can use the same "array style" access with the pointer str. You're looping over the individual chars you have allocated with new and are assigning them the value of the chars in the char array d.
// why? error: subscripts requires array or pointer type
Because you already dereference str (which is pointing at the start of the 6 element char array) with * which gives you a char, then you try to use that char like an array with [1] which makes no sense. *str would give you 'w' (the first element). And str[1] would give you *(str + 1) which is 'o' (the second element), don't double up.
A small-big side note, string literals are of type const char[], not char[], they're placed in read only memory and thus they can not be altered by the program (don't write to them).
char * strr = "morning";
This is very very bad, it treats a const char[] as a char[], this has been deprecated in the standard for a while now and according to the current standard this is even illegal, yet compilers still allow it for some reason.
Because compilers allow this you could get some nasty situations like trying to modify the string literal:
char * strr = "morning";
strr[0] = 'w'; // change to "worning"
This will attempt to write to read-only memory, which is undefined behaviour and will probably/hopefully get you a segmentation fault. Long story short, use the appropriate type to have the compiler stop you before the code reaches runtime:
const char * strr = "morning";
side side note : don't forget to delete anything you allocated with new.
This is a "how does it work" question. Based on my understanding, you have to initialize a non-dynamic array with a constant number of elements (int intarr[5]) or your array will write over blocks of memory that might be allocated for something else.
So why is it that you can initialize a string array (string strArray[]) without any elements?
Example:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s[] = {"hi", "there"};
cout << s[0] << s[1];
cin >> s[10]; //why is this ok?
cout << s[10];
return 0;
}
As a feature C++ (and C) allows you to declare an array without specifying the number of elements if you specify an initializer for it. The compiler will infer the number of elements that's needed.
So for
int intarr[] = { 1,2,3,4,5};
The compiler will see that the array need to have room for 5 ints, and this is will be exactly the same as if you stated:
int intarr[5] = {1,2,3,4,5};
A string array is just the same;
string s[] = {"hi", "there"};
is the same as if you wrote
string s[2] = {"hi", "there"};
Your code has a serious bug though;
string s[] = {"hi", "there"};
cout << s[0] << s[1];
cin >> s[10]; //why is this ok?
cin >> s[10]; is absolutely NOT ok. The array s has only 2 elements, and even if the compiler does not generate an error, you cannot use s[10]
Doing so results in undefined behavior - so it could appear to work, or it could crash, or it could do anything.
You can use string strArray[] in 2 ways
string strArray[] = {"apple","banana"};
or
void function(string strArray[]) {
...
}
In the first case, the size of the array is automatically determined by the number of initializers (2). In the second case, the size of the array is not needed because it is a formal argument.
Other than that, you must declare a size to the array. It doesn't matter if it is based on string or int.
If you are writing to s[10] in your example but only have 2 elements, you are writing to unallocated memory and the program behavior is undefined. It may not crash, but later on something bad will happen.
On VS (release), I run the following:
int main(void)
{
char b[] = "123";
char a[] = "1234567";
printf("%x %x\n", b,a);
return 0;
}
I can see that, the mem address of a is b+3(the length of the string). Which shows that the memory are allocated with no gaps. And this guarantee that least memories are used.
So, I now kind of believe that all compilers will do so.
I want to make sure of this guess here. Can somebody give me an more formal proof or tell me that my guess is rooted on a coincidence.
No, it's not guaranteed that there will always be perfect packing of data.
For example, I compiled and runned this code on g++, and the difference is 8.
You can read more about this here.
tl;dr: Compilers can align objects in memory to only addresses divisible by some constant (always machine-word length) to help processor(for them it's easier to work with such addresses)
UPD: one interesting example about alignment:
#include <iostream>
using namespace std;
struct A
{
int a;
char b;
int c;
char d;
};
struct B
{
int a;
int c;
char b;
char d;
};
int main()
{
cout << sizeof(A) << " " << sizeof(B) << "\n";
}
For me, it prints
16 12
There is no guarantee what addresses will be chosen for each variable. Different processors may have different requirements or preferences for alignment of variables for instance.
Also, I hope there were at least 4 bytes between the addresses in your example. "123" requires 4 bytes - the extra byte being for the null terminator.
Try reversing the order of declaring a[] and b[], and/or increase the length of b.
You are making a very big assumption about how storage is allocated. Depending on your compiler the string literals might get stored in a literal pool that is NOT on the stack. Yet a[] and b[] do occupy elements on the stack. So, another test would be to add int c and compare those addresses.
So this is a homework assignment, there might be come constraints that are ridiculous but please bear with me. This is just a simple function but drawn out. I need to return a character array via assignment operator but it doesn't seem to be working at all. I've tried pointers, but no luck.
#include <iostream>
using namespace std;
char* findMax(char*, char*);
int main()
{
char aArray[50] = "Hello World",
bArray[50] = "dlroW olleH",
maxArray[50];
maxArray[50] = findMax(aArray, bArray);
cout << maxArray << " is the bigger of the 2 strings" << endl;
return 0;
}
char* findMax(char* strA, char* strB){
char* maxStr;
if(strcmp(strA, strB) < 1)
maxStr = strB;
else
maxStr = strA;
return maxStr;
}
if I cout the return value of findMax() it does print out the value of bArray, but geting it into maxArray via assignment operator isn't working at all.
There are two ways to do this. As written, maxArray is an array of characters. Arrays can't be directly assigned to. Instead you need to copy each character one by one. You could do that with a loop, or by calling the strcpy standard library function.
char maxArray[50];
strcpy(findMax(aArray, bArray), maxArray);
The other way is to change the declaration of maxArray to be a char *, a pointer. Pointers can be assigned to directly without having to loop or invoke a function.
char *maxArray;
maxArray = findMax(aArray, bArray);
The difference between this and the first solution is subtle, but important. With char maxArray[50] you are actually allocating a third array of 50 characters, separate from aArray and bArray. This array has its own storage, its own 50 bytes of memory.
In the second you don't create a third array. You merely create a pointer which can point to other arrays already in existence. After the assignment, maxArray becomes an indirect reference to either aArray or bArray. It's not a copy of one of those arrays, it points to one of them.
#include<stdio.h>
#include<string.h>
#include<iostream.h>
using namespace std;
int main()
{
const char *a="hello";
char *b;
strcpy(b,a);
cout<<b;
return 0;
}
This code theows memory exception . why ?
char* b is a pointer that is yet to be pointed at any memory... it simply holds a random address. You attempt to copy the content of a over the memory at that address. Instead, first point b at some memory - either a local array or from new char[].
char buffer[128];
char* b = buffer;
char* b = new char[128];
// use b for a while...
delete[] b; // release memory when you've finished with it...
// don't read/write data through b afterwards!
( or simply copy it directly into buffer :-) )
BTW, C++ has a <string> header that's much, much easier to use:
#include <string>
int main()
{
std::string s = "hello";
std::string t = s;
std::cout << t << '\n'; // '\n' is a "newline"
}
If you're writing new code, prefer std::string, but sooner or later you'll need to know about all that char* stuff too, especially when C++ code needs to interact with C libraries.
Exception is due to uninitialized,
char *b;
Either allocate b on stack as an array,
char b[SIZE];
Or allocate using new and later delete it. But the best way is,
std::string b;
b = a;
Here
char *b;
strcpy(b,a);
b is not initialized - using its value is undefined behavior. Even if using its value is okay on your platform it holds "whatever" address - copying a string onto "whatever address" is undefined behavior.
You have to allocate a memory block by any legal means and set b to start of that block. The block must be large enough to hold the string together with terminating null character.
b is uninitialised. It is a pointer, but it doesn't point anywhere (it holds NULL or a garbage value). strcpy tries to write to it, but it must have a pointer to write to. You must assign some chunk of memory to b before you can use it. Eg:
char *b = new char[20]; //dynamically allocate some memory
or
char b[20]; //allocate some memory on the stack
A few things are "wrong" with your code.
Use:
#include <iostream>
You're not using C++ strings.
std::string a = "hello";
std::string b = a;
If you insist on using strcpy(), please allocate some memory for b:
b = new char[strlen(a)];
// Your code here
delete[] b;
There's lots of memory to go around. No need to go about corrupting stuff.
You need to allocate memory (e.g. using malloc) for the destination before you can copy something there.
The char pointer b is initiaized to 0 when the program runs. So you can't copy anything to it.
If you want to copy a string, in C++ style, do this instead:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a = "hello";
string b = a;
cout << b << endl;
return 0;
}
strcpy(dest, source)
In your code b is your dest and it is not initialized. Even if you switch them around it will still crash because you have not allocated memory for b. The destination memory has to be pre-allocated.