• Stack Overflow Public questions & answers
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Talent Build your employer brand
  • Advertising Reach developers & technologists worldwide
  • About the company

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Why is literal string assignment in C not possible for array with specified length? [duplicate]

Possible Duplicate: What is the difference between char s[] and char *s in C? Do these statements about pointers have the same effect?

All this time I thought that whenever I need to copy a string(either literal or in a variable) I need to use strcpy() . However I recently found out this:

From what I understand the second type is unsafe and will print garbage in some cases. Is that correct? What made me even more curious is why the following doesn't work:

but this works however

I would be greatful if someone could clear up things a bit.

Community's user avatar

3 Answers 3

char a[]="test";

This declares and initializes an array of size 5 with the contents of "test" .

char *a="test";

This declares and initializes a pointer to the literal "test" . Attempting to modify a literal through a is undefined behavior (and probably results in the garbage you are seeing). It's not unsafe, it just can't be modified since literals are immutable.

char a[5]; a="test";

This fails even when both a and "test" have the exact same type, just as any other attempt to copy arrays thorugh assignment.

char a[]; a="test";

This declares an array of unknown size. The declaration should be completed before being used.

char *a; a="test";

This works just fine since "test" decays to a pointer to the literal's first element. Attempting to modify its contents is still undefined behavior.

Jeff Widman's user avatar

Let's examine case by case:

This tells the compiler to allocate 5 bytes on the stack, put 't' 'e' 's' 't' and '\0' on it. Then the variable a points to where 't' was written and you have a pointer pointing to a valid location with 5 available spaces. (That is if you view a as a pointer. In truth, the compiler still treats a as a single custom type that consists of 5 char s. In an extreme case, you can imagine it something like struct { char a, b, c, d, e; } a; )

"test" (which like I said is basically 't' 'e' 's' 't' and '\0' ) is stored somewhere in your program, say a "literal's area", and a is pointing to it. That area is not yours to modify but only to read. a by itself doesn't have any specific memory (I am not talking about the 4/8 bytes of pointer value).

You are telling the compiler to copy the contents of one string over to another one. This is not a simple operation. In the case of char a[] = "test"; it was rather simple because it was just 5 push es on the stack. In this case however it is a loop that needs to copy 1 by 1.

Defining char a[]; , well I don't think that's even possible, is it? You are asking for a to be an array of a size that would be determined when initialized. When there is no initialization, it's just doesn't make sense.

You are defining a as a pointer to arrays of char . When you assign it to "test" , a just points to it, it doesn't have any specific memory for it though, exactly like the case of char *a = "test";

Like I said, assigning arrays (whether null-terminated arrays of char (string) or any other array) is a non-trivial task that the compiler doesn't do for you, that is why you have functions for it.

Shahbaz's user avatar

Do not confuse assignment and initialisation in C, they are different.

In C a string is not a data type, it is a convention , utilising an array and a nul terminator. Like any array, when you assign it, it's name resolves as a mere pointer. You can assign a pointer, but that is not the same as assigning a string.

Clifford's user avatar

Not the answer you're looking for? Browse other questions tagged c string initialization literals or ask your own question .

Hot Network Questions

c assign constant string to char array

Your privacy

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .

Why assigning string to const char* is possible?

c assign constant string to char array

Why assigning string to const char* at the initialization is possible (but it's not for normal char* , what is understable since it is a pointer to char, not char array)?

How does the program treats the value on the right side at the runtime (I'm talking about "This is word 1" string)? Does it handle it like a normal variable, temporary allocating memory for it and returning it's addres to word1 variable on the left side?

' src=

"foo" is actually {'f', 'o', 'o', '\0'} . Those 4 bytes end up in .data segment of your executable. Then the pointer to the start of that block gets assigned to word1 in const char* word1 = "foo";

What if I wrote „foo” in one line, without assigning it to anything? Would it be still in the memory after program goes past this line?

As pointed out string literals (other than when used as initializers) are made up of an array of const chars that are stored somewhere up to the implementation. An implementation is within it's rights to put it in read-only storage and/or to share the same char array with other occurrences of the same string literal.

One of the biggest pieces of standards dumb-assery was the 2003 version of the code declared string literals to be const char arrays but permitted an implicit conversion to char*. That is to say, your second statement would work in older compilers. The standard was gracious enough to declare actually changing the characters to be undefined behavior.

This was repaired in the 2011 standard. That special case conversion is no longer allowed.

It places it in some read-only block (.bss) in the exe (and it can be loaded to a read only block in the ram (if you will try to write to that block the OS will throw an exception))

It will not put it in .bss. .bss is uninitialized (though commonly zeroed out).

String literals go into special storage, you can't modify it. This is why it only binds to a const char pointer. Trying to bind to a char pointer implies mutability.

If you want a mutable C string holding a string literal then you can create an array on the heap and fill it manually.

const char* word1 = "word1";

This is syntactic sugar for something like:

Assigning a string literal to a non-const char* isn't allowed (unless you const_cast<> it) because the underlying memory backing such literals is const by definition. On platforms that support it the memory region containing them might be mapped as read-only.

as someone else pointed out, you can get a mutable buffer containing a string with:

which is shorthand for something like:

(although poking at that latter case in compiler explorer, gcc seems to generate instructions with the characters embedded as constants, rather than declaring a string variable in the data section and copying it over at runtime. Even if the same string is used multiple times like that in one function. clang declares a string constant and inserts a call to memcpy() .)

About Community

Ranked by Size

SEI CERT C Coding Standard

Space shortcuts

STR05-C. Use pointers to const when referring to string literals

The type of a narrow string literal is an array of char , and the type of a wide string literal is an array of wchar_t . However, string literals (of both types) are notionally constant and should consequently be protected by const qualification. This recommendation is a specialization of DCL00-C. Const-qualify immutable objects and also supports STR30-C. Do not attempt to modify string literals .

Adding const qualification may propagate through a program; as const qualifiers are added, still more become necessary. This phenomenon is sometimes called const-poisoning . Const-poisoning can frequently lead to violations of EXP05-C. Do not cast away a const qualification . Although const qualification is a good idea, the costs may outweigh the value in the remediation of existing code.

Noncompliant Code Example (Narrow String Literal)

In this noncompliant code example, the const keyword has been omitted:

If a statement such as c[0] = 'C' were placed following the declaration in the noncompliant code example, the code is likely to compile cleanly, but the result of the assignment would be  undefined because string literals are considered constant.

Compliant Solution (Immutable Strings)

In this compliant solution, the characters referred to by the pointer c are const -qualified, meaning that any attempt to assign them to different values is an error:

Compliant Solution (Mutable Strings)

In cases where the string is meant to be modified, use initialization instead of assignment. In this compliant solution, c is a modifiable char array that has been initialized using the contents of the corresponding string literal:

Consequently, a statement such as c[0] = 'C' is valid and behaves as expected.

Noncompliant Code Example (Wide String Literal)

If a statement such as c[0] = L'C' were placed following this declaration, the code is likely to compile cleanly, but the result of the assignment would be  undefined  because string literals are considered constant.

In cases where the string is meant to be modified, use initialization instead of assignment. In this compliant solution, c is a modifiable wchar_t array that has been initialized using the contents of the corresponding string literal:

Consequently, a statement such as c[0] = L'C' is valid and behaves as expected.

Risk Assessment

Modifying string literals causes undefined behavior , resulting in abnormal program termination and denial-of-service vulnerabilities .

Automated Detection

Related vulnerabilities.

Search for  vulnerabilities resulting from the violation of this rule on the CERT website .

Bibliography

c assign constant string to char array

Robert Seacord (Manager)

Shouldn't this be "Prefer making pointers to string literals const-qualified"?

David Svoboda

No, the title is correct. You are declaring the pointed-to chars const, not the pointer itself. Frankly I think you should use:

const char* const x = "hello";

as that prevents you from changing either the pointer or the pointed-to values, which is probably what you want.

Hallvard Furuseth

That doesn't make the title correct.  String literals aren't const-qualified in C, and you can't affect that.

"Prefer pointers to const for string literals", maybe.

And prepend "However," to the sentence "Adding const qualification may propagate...", and let that start a new paragraph.

Personally I'd not let that stand alone though. That is, I decide whether to constify something (whether pointing at a string literal or not) from how it'll be used.

Instead of your const char *x, I might instead write const char x[] which saves a pointer dereferencing at each access.

I changed the title and added an example using wide character strings, just for clarification.

Masaki Kubo

The first Compliant Solution (mutable strings) seems to have a contradiction between code example and its description. The second Compliant Solution (mutable strings) looks almost the same as the first one thus one of them can be cleared?

David Svoboda MGR

In the second CS shouldn't it use

Const wchar_t•

Rather than

Wchar_t const•

Alfredo Solano

It's equivalent. You can use the "read const from right to left" rule to check:

wchar_t const * is a pointer to const wchar_t

const wchar_t * is a pointer to wchar_t const

That is, it modifies what precedes it, unless it is in the left most position. In fact the narrow char example could also be written as:

char const  *c = "Hello";

which might be more appropriate (technically speaking) but most people find it less natural.

Joseph C. Sible

GCC and Clang have the flag -Wwrite-strings to warn when this recommendation isn't followed. Note that since it works under the hood by changing the type of string literals, rather than by directly enabling a warning, this won't be enabled by combination warning flags, not even Clang's -Weverything .

I added GCC and Clang to the Automated Detection sections to promote these features.

Related Articles

char* vs std:string vs char[] in C++

In this article, we are going to inspect three different ways of initializing strings in C++ and discuss differences between them.

1. Using char*

Here, str is basically a pointer to the (const)string literal. Syntax:

2. Using std::string

Here str is the object of std::string class which is an instantiation of the basic_string class template that uses char (i.e., bytes) as its character type. Note: Do not use cstring or string.h functions when you are declaring string with std::string keyword because std::string strings are of basic_string class type and cstring strings are of const char* type. Pros: When dealing exclusively in C++ std:string is the best way to go because of better searching, replacement, and manipulation functions. Some of the useful std:string functions are discussed below. 

Cases where you might prefer char* over std:string

3. Using char[]

Here are couple of other useful functions of C++ standard library cstring . 

This article is contributed by Kshitiz Gupta . If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to [email protected] See your article appearing on the GeeksforGeeks main page and help other Geeks. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Please Login to comment...

Improve your Coding Skills with Practice

Start your coding journey now.

Convert std::string to const char* in C++

This post will discuss how to convert a std::string to const char* in C++. The returned pointer should point to a char array containing the same sequence of characters as present in the string object and an additional null terminator (‘\0’ character) at the end.

1. Using string::c_str function

We can easily get a const char* from the std::string in constant time with the help of the string::c_str function. The returned pointer is backed by the internal array used by the string object, and if the string object is modified, the returned pointer will also be invalidated.

Download    Run Code

Output: std::string to const char*

2. Using string::data function

We can also call the string::data function on a std::string object to get const char* . This function works exactly like the string::c_str .

3. Using contiguous storage of C++11

We know that C++11 guarantees std::string ‘s memory allocation to be contiguous. So, we can get a pointer to the underlying char[] array behind std::string by invoking &str[0] or &*str.begin() . This approach will not work with C++98/03 standard.

That’s all about converting std::string to const char in C++.

Rate this post

Average rating 4.67 /5. Vote count: 24

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Tell us how we can improve this post?

guest

Stack Exchange Network

Stack Exchange network consists of 181 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle. It only takes a minute to sign up.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Is initializing a char[] with a string literal bad practice?

I was reading a thread titled "strlen vs sizeof" on CodeGuru , and one of the replies states that "it's anyways [sic] bad practice to initialie [sic] a char array with a string literal."

Is this true, or is that just his (albeit an "elite member") opinion?

Here is the original question:

right. the size should be the length plus 1 yes? this is the output the size of september is 8 and the length is 9 size should be 10 surely. its like its calculating the sizeof string before it is changed by strcpy but the length after. Is there something wrong with my syntax or what?

Here is the reply :

It's anyways bad practice to initialie a char array with a string literal. So always do one of the following:

Pacerier's user avatar

6 Answers 6

It's anyways bad practice to initialie a char array with a string literal.

The author of that comment never really justifies it, and I find the statement puzzling.

In C (and you've tagged this as C), that's pretty much the only way to initialize an array of char with a string value (initialization is different from assignment). You can write either

In the first case, the size of the array is taken from the size of the initializer. String literals are stored as arrays of char with a terminating 0 byte, so the size of the array is 8 ('o', 'c', 't', 'o', 'b', 'e', 'r', 0). In the second two cases, the size of the array is specified as part of the declaration (8 and MAX_MONTH_LENGTH , whatever that happens to be).

What you cannot do is write something like

etc. In the first case, the declaration of string is incomplete because no array size has been specified and there's no initializer to take the size from. In both cases, the = won't work because a) an array expression such as string may not be the target of an assignment and b) the = operator isn't defined to copy the contents of one array to another anyway.

By that same token, you can't write

where foo is another array of char . This form of initialization will only work with string literals.

I should amend this to say that you can also initialize arrays to hold a string with an array-style initializer, like

but it's easier on the eyes to use string literals.

In order to assign the contents of an array outside of a declaration, you would need to use either strcpy/strncpy (for 0-terminated strings) or memcpy (for any other type of array):

8bittree's user avatar

The only problem I recall is assigning string literal to char * :

For example take this program:

This on my platform (Linux) crashes as it tries to write to page marked as read-only. On other platforms it might print 'September' etc.

That said - initialization by literal makes the specific amount of reservation so this won't work:

But this will

As last remark - I wouldn't use strcpy at all:

While some compilers can change it into safe call strncpy is much safer:

Maciej Piechotka's user avatar

Primarily because you won't have the size of the char[] in a variable / construct that you can easily use within the program.

The code sample from the link:

string is allocated on the stack as 7 or 8 characters long. I can't recall if it's null-terminated this way or not - the thread you linked to stated that it is.

Copying "september" over that string is an obvious memory overrun.

Another challenge comes about if you pass string to another function so the other function can write into the array. You need to tell the other function how long the array is so it doesn't create an overrun. You could pass string along with the result of strlen() but the thread explains how this can blow up if string is not null-terminated.

You're better off allocating a string with a fixed size (preferably defined as a constant) and then pass the array and fixed size to the other function. @John Bode's comment(s) are correct, and there are ways to mitigate these risks. They also require more effort on your part to use them.

In my experience, the value I initialized the char[] to is usually too small for the other values I need to place in there. Using a defined constant helps avoid that issue.

sizeof string will give you the size of the buffer (8 bytes); use the result of that expression instead of strlen when you're concerned about memory. Similarly, you can make a check before the call to strcpy to see if your target buffer is large enough for the source string: if (sizeof target > strlen(src)) { strcpy (target, src); } . Yes, if you have to pass the array to a function, you'll need to pass its physical size as well: foo (array, sizeof array / sizeof *array); . – John Bode

Community's user avatar

One thing that neither thread brings up is this:

The former will do something like:

The latter only does the memcpy. The C standard insists that if any part of an array is initialized, it all is. So in this case, it's better to do it yourself. I think that may have been what treuss was getting at.

is better than either:

p.s. For bonus points, you can do:

to throw a compile time divide by zero error if you're about to overflow the array.

Richard Fife's user avatar

I think the "bad practise" idea comes from the fact that this form :

makes implicitly a strcpy from the source machine code to the stack.

It is more efficient to handle only a link to that string. Like with :

or directly :

(but of course in most code it probably doesn't matter)

toto's user avatar

Never is really long time, but you should avoid initialization char[] to string, because, "string" is const char*, and you are assigning it to char*. So if you pass this char[] to method who changes data you can have interesting behavior.

As commend said I mixed a bit char[] with char*, that is not good as they differs a bit.

There's nothing wrong about assigning data to char array, but as intention of using this array is to use it as 'string' (char *), it is easy to forget that you should not modify this array.

Dainius's user avatar

Not the answer you're looking for? Browse other questions tagged c programming-practices strings array or ask your own question .

Hot Network Questions

c assign constant string to char array

Your privacy

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .

The material in this page of notes is organized after "C Programming, A Modern Approach" by K.N. King, Chapter 13. Some content may also be from other sources.

String Literals

Passing String Literals to Functions String literals are passed to functions as pointers to a stored string. For example, given the statement: printf( "Please enter a positive value for the angle: " );
the string literal " Please enter . . . " will be stored somewhere in memory, and the address will be passed to printf. The first argument to printf is actually defined as a char *.

Continuing a String Literal

If a string literal needs to be continued across multiple lines, there are three options:

Operations on String Literals

char *prompt = "Please enter the next number: ";
prompt[ 0 ] = 'S'; // From above. Don't do this.

String Variables

String variables are typically stored as arrays of chars, terminated by a null byte. Initializing String Variables String variables can be initialized either with individual characters or more commonly and easily with string literals: char s1[ ] = { 'h', 'e', 'l', 'l', 'o', '\0' }; char s2[ ] = "hello"; // Array of size six char s3[ 20 ] = "hello"; // Fifteen null bytes char s4[ 5 ] = "hello"; // Five chars, sacrifices the null byte char s5[ 3 ] = "hello"; // Illegal

Character Arrays versus Character Pointers

Character arrays and character pointers are often interchangeable, but there can be some very important differences. Consider the following two variables:

char s6[ ] = "hello", *s7 = "hello";

Reading and Writing Strings

Writing Strings Using printf and puts The standard format specifier for printing strings with printf is %s The width parameter can be used to print a short string in a long space The .precision parameter limits the length of longer strings. int puts ( const char * str ); Writes the string out to standard output ( the screen ) and automatically appends a newline character at the end. This is a lower-level routine that printf, without formatting, and possibly faster. Reading Strings Using scanf, gets, and fgets The standard format specifier for reading strings with scanf is %s scanf reads in a string of characters, only up to the first non-whitespace character. I.e. it stops reading when it encounters a space, tab, or newline character. scanf appends a null byte to the end of the character string stored. scanf does skip over any leading whitespace characters in order to find the first non-whitespace character. The width field can be used to limit the maximum number of characters read. The argument passed to scanf needs to be of type pointer-to-character, i.e. char *, and is normally the name of a char array. ( In this case the size of the array -1 should be given as the width field, to make sure scanf can append the null byte without overflowing the array. char * gets ( char * str ); The gets function will read a string of characters from standard input ( the keyboard ) until it encounters either a newline character or the end of file. Unlike scanf, gets does not care about spaces in the input, treating them the same as any other character. Note that gets has no provision for limiting the number of characters read, leading to possible overflow problems. When gets encounters a new line character, it stops reading, but does NOT store it. A null byte is always appended to the end of the string of stored characters. char * fgets ( char * str, int num, FILE * stream ); fgets is equivalent to gets, except for two additional arguments and one key difference: num provides for a limit on the maximum number of characters read The FILE * argument allows fgets to read from any file. stdin may be entered to read from the keyboard. fgets stops reading when it encounters a new line character, and it DOES store the newline character. A null byte is always appended to the end of the string of stored characters. Reading Strings Character by Character Another option for reading in strings is to read them in character by character. This is useful when you don't know how long the string might be, or if you want to consider other stopping conditions besides spaces and newlines. ( E.g. stop on periods, or when two successive slashes, //, are encountered. ) The scanf format specifier for reading individual characters is %c If a width greater than 1 is given, then multiple characters are read, and stored in successive positions in a char array. Characters scanned this way are often stored in an array, although the could also be read into an ordinary char variable for further processing first.

Accessing the Characters in a String

Characters in a string can be acessed using either the [ ] notation or a char pointer.

Using the C String Library

size_t strlen ( const char * str ); Returns the length of the string, not counting the null byte char * strcpy ( char * destination, const char * source ); Copies characters from source to destination, until a null byte is eventually encountered char * strncpy ( char * destination, const char * source, size_t num ); Copies from source to destination, up to a maximum of num characters. Pads destination with extra null bytes if the length of source is smaller than num. May sacrifice the null byte if the source is longer than num. char * strcat ( char * destination, const char * source ); Concatenates ( appends ) source onto the end of destination. The terminating null byte of destination is over-written by the first char of source, and a new null-byte is appended at the end of the concatenated string. char * strncat ( char * destination, char * source, size_t num ); is a version that sets a limit on the number of characters concatenated. int strcmp ( const char * str1, const char * str2 ); Compares strings str1 and str2, up until the first encountered null byte Returns zero if the two strings are equal Returns a positive value ( 1? ) if the first encountered difference has a larger value in str1 than str2 Returns a negative value ( -1? ) if the first encountered differenc has a smaller value in str1 than str2 int strncmp ( const char * str1, const char * str2, size_t num ); checks only up to num characters. The methods stricmp and strnicmp do case-insensitive comparisons, but may be available for C++ programs only. int atoi (const char * str); double atof (const char* str); long int atol ( const char * str ); long long int atoll ( const char * str ); parses a string of numeric characters into a number of type int, double, long int, or long long int, respectively. Most often used when parsing command line arguments. Can also be used for rigorous checking of user input - Read in an entire line into a char array using gets, fgets, or char-by-char, then rigorously test all the characters in the string, ( e.g. are they all numeric ), and then use one of these routines to convert the char array into a number once all the checks have been made. sprintf( char [ ], format [ , data . . . ] ); "Prints" into a character array, similar to printf. Useful for converting data from other data types into a character string and/or combining things. sscanf( char *, format [ , address . . . ] ); Reads data from a character string, just as if scanf read it from the keyboard. One approach to rigorous input checking is to use getline( ) to read in an entire line of input from a user, then examine it character by character for any problems, e.g. non-numeric characters when trying to read in a number. Then when the string has been verified, use scanf to read in the data from the character string. See also strchr, strrchr, strstr, and strtok for searching and tokenizing strings.

String Idioms

Searching for the End of a String Copying a String void strcpy( const char * s, char * d ) { do { *d++ = *s++; } while( *s ); return; }

Arrays of Strings

Command Line Arguments

C++ Tutorial - String

cplusplus_icon.png

Strings is a source of confusion because it is not clear what is meant by string . Is it an ordinary charater array of type char* (with or without the const ), or an instance of class string ? In general, we use C-string for the type of char* or const char * and we use string for objects of C++ standard library.

C++ has two types of string:

In C, when we use the term string , we're referring to a variable length array of characters . It has a starting point and ends with a string-termination character. While C++ inherits this data structure from C, it also includes strings as a higher-level abstraction in the standard library.

The primary difference between a string and an array of characters revolves around length . Both representations share the same fact: they represent contiguous areas of memory. However, the length of an array is set at the creation time of the array whereas the length of a string may change during the execution of a program. This difference creates several implications, which we'll explore shortly.

Here is the quick summary:

Arrays can be implicity converted to pointers without casting. However, there is no implicit conversion from pointers to arrays.

Though the Standard C library is included as a part of Standard C++, to use C library, we need to include the C header file:

C string is stored as a character array. Actually, a string is a series of characters stored in consecutive bytes of memory. The idea of a series of characters stored in consecutive bytes implies that we can store a string in an array of char , with each character kept in its own array element.

C-style strings have a special feature: The last character of every string is the null character .

Both of these are arrays of char , but only the second is a string (an array of 9 characters). So, the 8-character string requires a 9-character array. This scheme makes finding the length of the string an O(n) operation instead of O(1) operation.

So, the strlen() must scan through the string until it finds the end. For the same reason that we can't assign one C array to another, we cannot copy C strings using '=' operator. Instead, we generally use the strcpy() function. However, note that it has also long been recommended to avoid standard library functions like strcpy() which are not bounds checked, and can cause buffer overflow.

we traverse it one by one each character:

The char* pointer str is dereferenced, and the character addressed is checked if it's true or false (if it's null).

Actually, a string literal may be used as an initializer in the declaration of either a character array or a variable of type char *. The declarations:

In both cases, each initialize a variable to the string "hello". The first declaration creates a six-element array str containing the characters 'h', 'e', 'l', 'l', 'o' and '\0'. The second declaration creates pointer variable pStr that points to the letter h in the string "hello", which also ends in '\0', in memory.

We cannot modify string literals; to do so is either a syntax error or a runtime error. String literals are loaded into read-only program memory at program startup. We can, however, modify the contents of an array of characters.

Attempting to modify one of the elements str is permitted, but attempting to modify one of the characters in pStr will generate a runtime error, causing the program to crash.

Just to get the feeling of C string, let's briefly look at the strlen() :

The length of a C string is determined by the terminating null-character. The length of a C string is the number of characters and the terminating null character is not included. Sometimes, we get confused with the size of the array that holds the string:

defines an array of characters with a size of 50 chars, but the C string, str , has a length of only 10 characters. So, sizeof(str) = 50 , but strlen(str) = 10 .

String literals have static storage class, which means they exist for the duration of the program. They may or may not be shared if the same string literal is referenced from multiple locations in a program. According to the C++ standard, the effect of attempting to modify a string literal is undefined. Therefore, we should always declare a pointer to a string literal as const char * .

Since there are still many program situations which require understanding C-style string, we need to be familiar with the C-style string.

Let's find out how much we know about C-string using the examples below. Can you figure out what's wrong?

Answer 1 Compiles successfully. In run time, however, at the moment when it tries to write, it fails. We get this message: Unhandled exception at 0x00411baa in cstring.exe: 0xC0000005: Access violation writing location 0x0041783c.

When our program is compiled, the compiler forms the object code file, which contains our machine code and a table of all the string constants declared in the program. In the statement, char *cstr1 = "hello"; causes cstr1 to point to the address of the string hello in the string constant table. Since this string is in the string constant table, and therefore technically a part of the executable code, we cannot modify it. We can only point to it and use it in a read-only manner.

The "hello" is a string literal (or string constant) because it is written as a value, not a variable. Even though string literals don't have associated variables, they are treated as const char* 's (arrays of constant characters). String literals can be assigned to variables, but doing so can be risky. The actual memory associated with a string literal is in a read-only part of memory, which is why it is an array of constant characters. This allows the compiler to optimize memory usage by reusing references to equivalent string literals (that is, even if your program uses the string literal "hello" 100 times, the compiler can create just one instance of hello in memory). The compiler does not, however, force our program to assign a string literal only to a variable of type const char* or const char[]. We can assign a string to a char* without const, and the program will work fine unless you attempt to change the string, which is what we're trying to do in the last line of the Question #1.

Answer 3 This won't compile.

At the line: cstr3 = "hello"; we get the following message: cannot convert from 'const char [6]' to 'char [100]'

Since the string hello exists in the constant table, we can copy it into the array of characters named cstr3 . However, it is not a pointer, the statement cstr3="hello"; will not work.

We can think of the problem this way: the pointer we get from the name of an array as a pointer to its first element is a value NOT a variable , so we cannot assign to it.

In fact, an array name is a constant pointer to the first element of the array. As a consequence of this implicit array-name-to-pointer conversion, we can't even copy arrays using assignment:

Answer 4 No problem at all.

In general, the Asnwers from 1 to 4 may vary depending on compiler. So, the best way of avoiding unexpected run-time error, is to use a pointer to const characters when referring to string literals :

Standard C library gives us a set of utility functions such as:

Some of the source code for the library utility functions can be found Small Programs .

Because we manipulate the C string using pointer which is low-level operation, it's error prone. That's why we have C++ <string> class.

Though there are lots of advantages of C++ string over C string, we won't talk about it at this time. But because numerous codes still using C style string, we need to look at the conversion between them. Here is an example with some error messages we'll get if we run it as it is.

The c_str() returns the contents of the string as a C-string. Thus, the '\0' character is appended. Actually, it returns a pointer to const array in order to prevent the array from being directly manipulated. That's why we need const qualifier in the example code. Note that C++ strings do not provide a special meaning for the character '\0' , which is used as special character in an ordinary C-string to mark the end of the string. The character '\0' is part of a string just like every other character.

Here are the couple of ways to initialize a string:

The string class provides several constructors. If we define a string type without explicitly initializing it, then default constructor is used.

C++ provides two forms of variable initialization:

Note that initialization and assignment are different operations in C++. When we do initialization, a variable is created and given its initial value. However, when we do assignment, an object's current value is obliterated and replaced with a new one. For a built-in type variable like int, there is little difference between the direct and the copy forms of initialization. However, when we deal with more complex types, the difference becomes clear. The direct initialization tends to be more efficient.

Assign s2 to s1 ; s2 can be a string or a C-style string .

Add a at end; a can be a character or a C-style string .

subscripting

Concatenation; the characters in the resulting string will be a copy of those from s1 followed by a copy of those from s2 .

Lexicographical comparison of string values; s1 or s2 , but not both, can be a C-style string.

Comparison of string values; s1 or s2 , but not both, can be a C-style string.

Number of characters in s .

C-style version of characters in s .

Iterator to first character.

Iterator to one beyond the end of s .

Insert a before s[pos] ; a can be a character, a string , or a C-style string. s expands to make room for the characters from a .

Insert a after s[pos] ; a can be a character, a string , or a C-style string. s expands to make room for the characters from a .

Remove the character in s[pos] ; s 's size decreases by 1.

Find a in s ; a can be a character, a string , or a C-style string. pos is the index of the first character found, or npos (a position off the end of s . Wat if we can't find the string as in the example below? if(s.find("mystring") == string::npos) cout << "can't find it \n"; Because "mystring" does not exist in "s", find() returns a constant which we access with string::npos . As a result, it displays the message. The string::npos represents the largest possible size of a string object, and it means a position that can't exist. So, it is the perfect return value to indicate the failure of finds

Read a whitespace-separated word into s from in .

Read a line into s from in .

Write from s to out .

Take a look at the following code:

The name of an array is the address of its first element. The name in the cout is the address of the char element containing the character A . The cout object assumes that the address of a char is the address of a string. So, it prints the character at that address and then continues printing characters until it meets the null character, '\0' .

In other words, a C string is nothing more than a char array. Just as C doesn't track the size of arrays, it doesn't track the size of strings. Instead, the end of the string is marked with a null character, represented in the language as '\0'. So, if we give the cout the address of a character, it prints everything from that character to the first null character that follows it.

The key here is that name acts as the address of a char which implies that we can use a pointer-to- char variable as an argument to cout .

What about the other part of the cout statement? If name is actually the address of the first character of a string, what is the expression " is one of the greatest.\n" ? To be consistent with cout 's handling of string output, this quoted string should also be an address. Yes, it is. A quoted string serves as the address of its first element.

The following example shows how we use different forms of strings. It uses two functions from the string library, strlen() and strcpy(). Prototypes of the functions are in cstring header file.

Output from the run:

"Edsger W. Dijkstra" to the namePtrConstChar pointer.

String literals are constants , which is why the code uses the const keyword. Using const means we can use namePtrConstChar to access the string but not to change it .

The pointer ptr remains uninitialized, so it doesn't point to any string.

The code illustrates that we can use the array name nameArr and the pointer namePtrConstChar equivalently with cout . Both are the addresses of strings, and cout displays the two strings stored at those addresses.

Let's look at the following code of the example:

It produces the following output:

In general, if we give cout a pointer, it prints an address. But if the pointer is type char * , cout displays the pointed-to-string. If we want to see the address of the string, we should cast the pointer to another pointer type, such as int * . Thus, ptr displays as the string "Alan Turing", but (int *)ptr displays as the address where the string is located. Note that assigning nameArr to ptr does not copy the string, it copies the address. This results in the two pointers ( nameArr and ptr ) to the same memory location and string.

To get a copy of a string, we need to allocate memory to hold the string. We can do this:

In the code, we use the second approach:

Then, we copy a string from the nameArr to the newly allocated space. It doesn't work if we assign nameArr to ptr because it just changes the address stored in ptr and thus loses the information of the address of memory we just allocated. Instead, we need to use the strcpy() :

The strcpy() function takes two arguments. The first is the destination address, and the second is the address of the string to be copied. Note that by using strcpy() and new , we get two separate copies of "Alan Turing" :

Additional codes related to string manipulation samples which frequently appear at interviews are sources A and sources B

DoBong

Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

Sponsor Open Source development activities and free contents for everyone.

C++ Tutorials

IMAGES

  1. Char array to string in C++

    c assign constant string to char array

  2. Convert Character Array to Char in C#

    c assign constant string to char array

  3. A Programmer's Day: c++ string to char array

    c assign constant string to char array

  4. C initialize std::array

    c assign constant string to char array

  5. 38. Two D char Array for String in C++ (Hindi)

    c assign constant string to char array

  6. C# String Array [Explained with 4 Examples]

    c assign constant string to char array

VIDEO

  1. 05 Data Structures Introduction and Array

  2. Array C++

  3. C++

  4. R programlamada Vektör Oluşturma #rprogramming #rprogramlama c(),assign()

  5. C++ (char array)

  6. Java Program to convert Character or Character array to String

COMMENTS

  1. Why is literal string assignment in C not possible for array with

    In C a string is not a data type, it is a convention, utilising an array and a nul terminator. Like any array, when you assign it, it's name

  2. Why assigning string to const char* is possible?

    As pointed out string literals (other than when used as initializers) are made up of an array of const chars that are stored somewhere up to the

  3. Can we assign a string to a char array in C?

    #include <iostream> · int main() { · char array[] = "Hello, world!\n"; · char *cp = array; · const char *ccp = cp; · std::cout << ccp;. }.

  4. Is a 'const char array []' considered a string?

    Originally, the C language did not have a const type qualifier. So string literals had type “array of char ”, which usually implicitly converted to a

  5. STR05-C. Use pointers to const when referring to string literals

    In cases where the string is meant to be modified, use initialization instead of assignment. In this compliant solution, c is a modifiable char array that has

  6. char* vs std:string vs char[] in C++

    No need to declare the size of string beforehand. ... in C string literals are arrays of char but in C++ they are constant array of char.

  7. Convert std::string to const char* in C++

    This post will discuss how to convert a std::string to const char* in C++. The returned pointer should point to a char array containing the same sequence of

  8. Is initializing a char[] with a string literal bad practice?

    It's anyways bad practice to initialie a char array with a string literal. The author of that comment never really justifies it

  9. C Programming Course Notes

    Instead C stores strings of characters as arrays of chars, terminated by a ... A String Literal, also known as a string constant or constant string, is a

  10. C++ Tutorial: String

    We should always declare a pointer to a string literal as const char *. strlen(pHello)=5, the terminating null character is not included. To store C++ string to