This question already has answers here:
Non null-terminated string compiler option for gcc
(6 answers)
Closed 7 years ago.
I am trying to initialize a char array with a long string. However, I do not want it to be NULL terminated.
This:
const char s[] = "The actual string is much longer then this...";
is much easier to read (and to write) than this:
const char s[] = {'T', 'h', 'e', ' ', 'a', 'c', 't', 'u', 'a', 'l', ' ', 's', ...};
but the former gets NULL terminated. Is there a way to avoid the NULL on a string literal?
The reason for doing this is that there is the need to pack densely strings in memory of fixed size length known during development.
No.
A string literal is a C-string which, by definition, is null-terminated.
Either ignore the final character, revisit your requirements (why do you care about a final character?!) or … I dunno, something else. Perhaps generate the objects with xxd?
I would do:
size_t length = 45;
char s[] = "The actual string is much longer then this..";
s[length - 1] = ".";
See what you have there has a trade-off between readability and functionality and I think that you can get away easily with this, since you can not avoid the NULL terminating string in the "normal" initialization.
If I were in your shoes, I would re-consider my approach and use std::string.
No. If you want essy to write code, copy to a second array but miss off the last char. You can use a char pointer in the first case to perhaps save some memory
The terminating nul will be omitted if it doesn't fit. Since your strings are all fixed length, that's not a problem to arrange. For example:
#include <stdio.h>
char foo[3][4] = { "four", ".by." , "3333" };
int main(void)
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
putchar(foo[i][j]);
putchar('\n');
}
}
There is no way to have a string literal not null terminated.
But you actually want to pack a number of strings densely and you know both the sizes and the strings at development time.
Assume:
"First"
"Second"
"Third"
to pack them you can safely do:
char const s[] = "First""Second""Third";
You only need to save lengths and properly reconstruct termination in case you want to print or use std string. That is easy though.
As a bonus you have saved from the excess pointer you would have to store for each and everyone string needed.
Related
I am learning c++ from a book, but I am already familiar with programming in c# and python. I understand how you can create a char pointer and increment the memory address to get further pieces of a string (chars), but how can you get the length of a string with just a pointer to the first char of it like in below code?
Any insights would help!
String::String(const char * const pString)
{
Length = strlen(pString)
}
This behavior is explained within the docs for std::strlen
std::size_t std::strlen(const char* str);
Returns the length of the given byte string, that is, the number of characters in a character array whose first element is pointed to by str up to and not including the first null character. The behavior is undefined if there is no null character in the character array pointed to by str.
So it will count the number of characters up to, but not including, the '\0' character. If this character is not encountered within the allocated bounds of the character array, the behavior is undefined, and likely in practice will result in reading outside the bounds of the array. Note that a string literal will implicitly contain a null termination character, in other words:
"hello" -> {'h', 'e', 'l', 'l', 'o', '\0'};
You can implement your own method in C-style like:
size_t get_length(const char * str) {
const char * tmp = str;
while(*str++) ;
return str - tmp - 1;
}
I am new to c++ language,recently, as I was taught that:
we should put '\0' at the end of char array while doing initialization ,for example :
char x[6] = "hello"; //OK
However,if you do :
char x[5] = "hello";
Then this would raise the error :
initializer-string for array of chars is too long
Everything goes as I expect until the experssion below does not raise the compile error...:
char x[5] = {'h','e','l','l','o'};
This really confuses me , So I would like to ask two questions :
1.Why doesn't expression char x[5] = "hello"; raise error?
2.To my knowledge,the function strlen() would stop only if it finds '\0' to determine the lengh of char array,in this case,what would strlen(x) return?
Thanks!
The string literal "hello" has six characters, because there's an implied nul terminator. So
char x[] = "hello";
defines an array of six char. That's almost always what you want, because the C-style string functions (strlen, strcpy, strcat, etc.) operate on C-style strings, which are, by definition, nul terminated.
But that doesn't mean that every array of char will be nul terminated.
char x[] = { 'h', 'e', 'l', 'l', 'o' };
This defines an array of five char. Applying C-style string functions to this array will result in undefined behavior, because the array does not have a nul terminator.
You can do character-by-character initialization and create a valid C-style string by explicitly including the nul terminator:
char x[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
This defines an array of six char that holds a C-style string (i.e., a nul terminated sequence of characters).
The key here is to separate in your mind the general notion of an array of char from the more specific notion of an array of char that holds a C-style string. The latter is almost always what you want to do, but that doesn't mean that there is never a use for the former. It's just that the former is uncommon.
As an aside, in C you're allowed to elide the nul terminator:
char x[5] = "hello";
this is legal C, and it creates an array of 5 char, with no nul terminator. In C++ that's not legal.
Why doesn't expression char x[5] = "hello"; raise an error?
This is not true. The appearance of an error is expected in this case.
To my knowledge, the function strlen() would stop only if it finds '\0' to determine the length of the char array, in this case, what would strlen(x) return?
If you can run the code somehow, the program will undergo an undefined-behavior. That is, you will not get what you would expect. The strlen() will only stop counting when it finds a null-terminator, i.e. it may go outside the initialized part of the char array and access the uninitialized ones – it's where the UB is invoked.
This question already has answers here:
What is a null-terminated string?
(7 answers)
Closed 2 years ago.
There is a saying when we declare char variable.
We should declare like this -> char ArrayName[Maximum_C-String_Size+1];
For example:
char arr[4+1] = {'a', 'b', 'c', 'd'}
but
arr[4] = {'a', 'b', 'c', 'd'} is also work
why need to add 1?
thanks!
There is no need to do this, unless you are defining something that will be used as a null-terminated string.
// these two definitions are equivalent
char a[5] = { 'a', 'b', 'c', 'd' };
char b[5] = { 'a', 'b', 'c', 'd', '\0' };
If you only want an array with 4 char values in it, and you won't be using that with anything that expects to find a string terminator, then you don't need to add an extra element.
If you’re storing a C-style string in an array, then you need an extra element for the string terminator.
Unlike C++, C does not have a unique string data type. In C, a string is simply a sequence of character values including a zero-valued terminator. The string "foo" is represented as the sequence {'f','o','o',0}. That terminator is how the various string handling functions know where the string ends. The terminator is not a printable character and is not counted towards the length of the string (strlen("foo") returns 3, not 4), however you need to set aside space to store it. So, if you need to store a string that’s N characters long, then the array in which it is stored needs to be at least N+1 elements wide to account for the terminator.
However, if you’re storing a sequence that’s not meant to be treated as a string (you don’t intend to print it or manipulate it with the string library functions), then you don’t need to set aside the extra element.
I'm new to c++ and I'd like to know right from the start,
Does any of these methods of making strings work exactly the same way and give the exact same results always in every case? is there any difference in the result in any of them?
1) char greeting [6] = { 'h','e','l','l','o','\0' };
2) char greeting[] = "hello";
3) #include <string>
string greeting = "hello";
1) and 2) work exactly the same. Both create a 6-element non-heap-allocated array, and copy the characters 'h', 'e', 'l', 'l', 'o', '\0' to the array at runtime or load time.
3) creates an instance of std::string and calls its constructor which copies the characters 'h', 'e', 'l', 'l', 'o'(, '\0')* to its internal memory buffer. (* The '\0' is not required to be stored in the memory buffer.)
There is another way to declare a string in C++, using a pointer to char:
const char* greeting = "hello";
This will not copy anything. It will just point the pointer to the first character 'h' of the null-terminated "hello" string which is located somewhere in memory. The string is also read-only (modifying it causes undefined behavior), which is why one should use a pointer-to-const here.
If you're wondering which one to use, choose std::string, it's the safest and easiest.
Do these methods of making strings work exactly the same way and give the exact same results always in every case?
The first two are array definitions:
char greeting [6] = { 'h','e','l','l','o','\0' };
char greeting [ ] = "hello";
"work the same" as in the second definition a '\0' is appended implicitly.
As for the third definition:
string greeting = "hello";
A string is a class type object and as such it is more complex than a simple array.
Is there any difference in the result in any of them?
There is a quantitative1 and qualitative2 difference between the first two and the third stemming from the fact that std::string is a class type object.
1. Quantitative: arrays occupy less memory space than string.
2. Qualitative: string provides resource management and many facilities for element manipulation.
I read that when one inicializes an array it is possitle to use a string literal.
But if the list if inicializers is bigger than the size of array, an error is caught.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char cAr2[3] = "ABC";
for (int i = 0; i < 3; i++)
cout<<cAr2[i]<<endl;
system("pause");
return 0;
}
Well, this example is given in my book.
It really ends like this: error C2117: 'cAr2' : array bounds overflow.
Could you tell me what is what here: I can see an array of 3 elements and 3 elements being placed into it. Everything seems Ok. Why error?
The string literal "ABC" gives you an "array of 4 const char". There are 4 characters because the string is terminated with the null character. That is, your initialisation would be equivalent to:
char cAr2[] = {'A', 'B', 'C', '\0'};
The null character is implicitly appended to the end of your string so that algorithms that loop over the contents of the array know when to stop without having a string length explicitly given.
Well, the easy answer is this: if you're going to use an initializer, save yourself some grief and leave out the size.
The longer answer is that strings are null-terminated, which means there's an additional character you do not see at the end of the string. So you will need an array of size n+1 where n is the number of characters you see.
The size 3 is not large enough for the "ABC" string:
char cAr2[3] = "ABC";
You need at least 4 characters to store this string with the null terminator
Even if your compiler auto corrects that (I am not sure), it is not a good idea to undersize the array..
If you want to initialize using a string literal I think you'll want to do something like this:
char *cAr2 = "ABC";
However, if you'd like to keep the same type do this:
char cAr2[3] = { 'A', 'B', 'C' };