This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 7 years ago.
I am having a difficult time obtaining the correct size of a string in order to satisfy strcpy_s. For example if I specify
char buffer = {0};
char *str1 = (char*)&buffer;
strcpy_s(str1,sizeof("This is a string\n"),"This is a string\n");
Then it will work as expected. If however I declare the following:
char buffer = {0};
char *str1 = (char*)&buffer;
const char* string1 = "This is a string.....";
strcpy_s(str1, ?????,string1);
If I use anything other than a literal in place of ????? it will fail with a memory exception, for example if I use std:strlen(str1), etc. Any size literal for ???? will work. Of course using a fixed literal is not acceptable.
This is a major re-edit of the original question and I apologise to the people who have answered to date. However none of the the answers below have worked.
"This is a string" is a character array. When you say sizeof(Array)/sizeof(type) it will give the size of the array
When you define the string as const char* then the sizeof(pointer) gives the size allocated for the pointer no the array size
const char* ptr = "This is a string\n";
std::cout<<sizeof("This is a string\n")<<std::endl; //==>18
std::cout<<sizeof(ptr)<<std::endl; //==>4
First of all, the second parameter is the size of the destination buffer, not the size of the source buffer.
so the correct way is:
char str1[100];
strcpy_s(str1, sizeof str1, "Whatever string");
or
int n = 100;
char *str1 = new char[n];
strcpy_s(str1, n, "whatever string");
For an array (first example) sizeof returns the size of the array.
For a pointer (second example) sizeof returns the size of the pointer (which is not what you want)
In your second example, string1 is of type const char*. sizeof will return the size of the pointer, rather than the length of the string literal you are pointing to.
The first example works because a string literal is a const char[], and sizeof will correctly return the length of the string (but with the null terminating character as well). It's only coincidental that this works because char is 1 byte. Do not use sizeof to get string lengths.
To make your second example work, try using std::strlen.
Related
This question already has answers here:
What happened when we do not include '\0' at the end of string in C?
(5 answers)
What is the difference between char s[] and char *s?
(14 answers)
Why do string literals (char*) in C++ have to be constants?
(2 answers)
Closed last year.
I am a C++ newbie. Although many similar questions have been asked and answered, I still find these concepts confusing.
I know
char c='a' // declare a single char c and assign value 'a' to it
char * str = "Test"; // declare a char pointer and pointing content str,
// thus the content can't be modified via point str
char str1[] = "Test"; // declare a char array str1 and assign "Test" to it
// thus str1 owns the data and can modify it
my first question is char * str creates a pointer, how does char * str = "Test"; work? assign a string literal to a pointer? It doesn't make sense to me although it is perfectly legal, I think we can only assign an address to a pointer, however "Test" is a string literal not an address.
Second question is how come the following code prints out "Test" twice in a row?
char str2[] = {'T','e','s','t'}; // is this line legal?
// intializing a char array with initilizer list, seems to be okay to me
cout<<str2<<endl; // prints out "TestTest"
why cout<<str2<<endl; prints out "TestTest"?
char * str = "Test"; is not allowed in C++. A string literal can only be pointed to by a pointer to const. You would need const char * str = "Test";.
If your compiler accepts char * str = "Test"; it is likely outdated. This conversion has not been allowed since C++11 (which came out over 10 years ago).
how does char * str = "Test"; work?
String literals are implicitly convertible to a pointer to the start of the literal. In C++ arrays are implicitly convertible to pointer to their first element. For example int x[10] is implicitly convertible to int*, the conversion results in &(x[0]). This applies to string literals, their type is a const array of characters (const char[]).
how come the following code prints out "Test" twice in a row?
In C++ most features related to character strings assume the string is null terminated, which is implied in string literals. You would need {'T','e','s','t','\0'} to be equivalent to "Test".
This question already has answers here:
What is the difference between a Character Array and a String?
(10 answers)
Closed 9 years ago.
I want to know the difference between character array and string in c++.
Can any one answer to this??
Please,
Thanks
Vishnukumar
string is a class/object, with methods and encapsulated data.
A char array is simply a contiguous block of memory meant to hold chars.
(1) char array is just a block of char type data:
e.g. char c[100]; // 100 continuous bytes are allotted to c
(2a) By string, if you mean char string then, it's little similar to array but it's allocated in the readonly segment of the memory and should be assigned to a const char*:
e.g. const char *p = "hello"; // "hello" resides in continuous character buffer
[note: char c[] = "hello"; belongs to category (1) and not to (2a)]
(2b) By string if yo umean std::string then, it's a standard library class from header and you may want to refer its documentation or search on web
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between char a[] = “string”; and char *p = “string”;
Could you please explain what is the difference between these? ^^
//difference between:
char* sz1 = "blah";
char sz2[] = "blah";
//and also please explain these
char *sz3 = new char[512];
char *sz4[512] = { 0, };
char sz5[512];
"blah" is a const char [5]. In the first line, that array is decayed into a pointer to be stored in your variable as a pointer to the first element. It is also a pointer to non-const characters that points to const characters. It should be:
const char *sz1 = "blah";
In the second (thanks jrok), it creates an actual array and initializes it with {'b', 'l', 'a', 'h', '\0'}.
char *sz3 = new char[512];
This allocates 512 * sizeof (char) bytes of memory for the chars and sz3 will point to the beginning. This is stored on the heap, as opposed to the stack, so don't forget to delete[] it.
char *sz4[512] = { 0, };
This creates an array of 512 pointers to characters and initializes them all to 0 (NULL). The comma isn't needed, it's just easier to add onto the initializer list afterwards. The spiral rule can be used here to determine sz4 is an array of 512 (one right) pointers (one left) to char (two left).
char sz5[512];
This creates an array (on the stack) of 512 characters.
All but the second-last can effectively be replaced with std::string.
The First two examples are essentially the same, char pointers with memory assigned to them at runtime.
The third one, you are allocating 512 bytes worth of memory and assigning sz3 the address of it.
For the fourth one you are declaring an array of 512 char pointers, but your assignment (to the best of my knowledge) is incorrect.
And Finally, the fifth statement creates an array of 512 chars.
I have got a const char which is made by concatenation like this:
const char *fileName = "background1";
std::stringstream sstm;
sstm << fileName << "-hd.png";
fileName = sstm.str().c_str();
My problem is that the following instruction:
printf("const char = %s size = %d", fileName, sizeof(fileName));
returns:
"const char = background1-hd.png size = 4"
whereas I would expect that it returns:
"const char = background1-hd.png size = 19"
For example, the following gives the convenient result (as there is no concatenation):
const char *fileName2 = "background1-hd";
printf("const char = %s size = %d", fileName2, sizeof(fileName2));
returns:
"const char = background1-hd.png size = 19"
How to avoid this issue and guarantee that the characters will be correctly counted in my concatenated char ?
Thanks !!
sizeof() returns the number of bytes the variable occupies in memory (in this case returns the size of the pointer fileName).
strlen() returns the length of the string (which is what you need).
You could as well try something like:
#include <iostream>
#include <cstdio>
int main()
{
std::string fileName("background1");
fileName.append("-hd.png");
printf("const char = %s size = %d", fileName.c_str(), fileName.length());
return 0;
}
sizeof returns the size of the variable you give to it; it's evaluated at compile time. The "4" is the size of a pointer on your system. You want to use strlen() to determine the length of a string.
The result of sizeof(fileName) is related to fileName being a pointer, not an array. It literally returns the size of a pointer to a constant character string, and on a 32-bit system, all pointers are 32 bits (so sizeof == 4).
What you should use instead is strlen or similar, which will count the characters in the string, up to the trailing null, and return that. The results with strlen in place of sizeof will be about what you expect.
Side-related, with const char strings there is only ever one character per "cell" (actually byte). There are character sets which make for multiple bytes per character, but packing multiple characters into a single byte is quite rare, at least in C-family languages.
sizeof calculates the size of the data type in bytes and not the size of its contents (what it points to). In your example you are calculating the sizeof char* which is 4 bytes on your system. To get the length of a C string use strlen.
There is a distinction in the language between arrays and pointers, even if this distinction seems diluted both by implicit conversions (arrays tend to decay into pointers quite easily), and common statements that they are the same.
How does this even relate to your code?
Well, a string literal is actually an array of constant characters, not a pointer to character(s). In the initialization const char *fileName = "background1"; you are creating a pointer variable that points to the first element of the array ("background1" is decaying into a pointer to the first element), and from there on the variable you are managing is pointer and not the literal.
If you mix this with the fact that sizeof will tell you the size of the variable, you get that in a platform with 32bit pointers and 8 bit chars, sizeof( const char* ) is always 4, regardless of the object that is pointed by that pointer (if there is even one).
Now, if you were treating the literal as what it actually is you would be having a bit more luck there:
const char filename[] = "background1";
assert( sizeof filename == 12 ); // note: NUL character is counted!
const char *fname = filename;
assert( sizeof filename == sizeof( void* ) );
In real code, you are not a so lucky and in many cases the literals have decayed into pointers well before you get a chance of getting the compile time size of the literal, so you cannot ask the compiler to tell you the size. In that case you need to calculate the length of the C style string, which can be done by calling strlen.
strlen has been suggested a number of times already, and for this case it's probably perfectly reasonable.
There is an alternative that will let you use sizeof though:
char fileName[] = "background1";
std::cout << sizeof(fileName) << "\n";
Since you're making fileName an array, it has all the characteristics of an array -- including the fact that your later attempt at assigning to it:
fileName = sstm.str().c_str();
...would fail (won't even compile when fileName is defined as an array). I should add, however, that it seems to me that you'd be better off just using std::string throughout:
std::string fileName("background1");
std::stringstream sstm;
sstm << fileName << "-hd.png";
fileName = sstm.str();
In this case, you can use string's size() or length() member.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C - Difference between “char var[]” and “char *var”?
Difference between char a[]=“string”; char *p=“string”;
would someone explain what exactly the difference between char[] and char* is?
for example difference between
char name[] = "earth";
and
char *name = "earth";
thanks
char namea[] = "earth";
char *pname = "earth";
One is an array (the name namea refers to a block of characters).
The other is a pointer to a single character (the name pname refers to a pointer, which just happens to point to the first character of a block of characters).
Although the former will often decay into the latter, that's not always the case. Try doing a sizeof on them both to see what I mean.
The size of the array is, well, the size of the array (six characters, including the terminal null).
The size of the pointer is dependent on your pointer width (4 or 8, or whatever). The size of what pname points to is not the array, but the first character. It will therefore be 1.
You can also move pointers with things like pname++ (unless they're declared constant, with something like char *const pname = ...; of course). You can't move an array name to point to it's second character (namea++;).
(1) char name[] = "earth";
name is an character array having the contents as, 'e','a','r','t','h',0. The storage location of this characters depends on where name[] is declared (typically either stack or data segment).
(2) char *name = "earth";
name is a pointer to a const string. The storage location of "earth" is in read-only memory area.
In C++, this is deprecated and it should be const char *name = "earth";
char name[]= "earth"; creates a mutable array on the stack with the size of 6 with the value earth\0.
char* name = "earth"; defines a pointer to a string constant with the value earth\0.
char[] describes an array of char with a fixed number of elements.
char* describes a pointer to a char, typically followed in memory by a sequence of char's typically terminated by a null char \0
With
char *name = "earth"
you must not modify the contents of name.
Hence
name[2] = 'A';
char* is terminated by a '\0' character while name[] has fixed size.
will cause a segfault.
Initializing the variable takes a huge performance and space penalty
for the array. Only use the array method if you intend on changing the
string, it takes up space in the stack and adds some serious overhead
every time you enter the variable's scope. Use the pointer method
otherwise.