This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Difference between char a[]=“string”; char *p=“string”;
Firstly, i would like to ask where can i learn all the basics of char* and char[].
Most of the time i find myself struggling with how to compare and how to declare.
Example 1 :
char *test = "hello world";
This will produce the following warning at compilation :
warning: deprecated conversion from string constant to ‘char*’
Example 2 :
vector<char*> test2;
test2.push_back("hello world");
This will produce an error of copying a string.
So the solution i come up with is :
(is this correct?)
vector<char*> test3;
char *str1 = "hello world"
test3.push_back(str1);
Thanks in advance! :)
============================================
Two good reads provided by people here :
What is the difference between char s[] and char *s?
Difference between char a[]="string"; char *p="string";
Your question "where can i learn all the basics of char* and char[]," is probably too general, but you can try reading the C++ spec.
Fix example 1 by changing it to
char const *test = "hello world";
Fix example 2 by changing it to
vector<std::string> test2;
test2.push_back("hello world");
Or if you really want a vector of non-owning pointers to c-strings:
vector<char const *> test2;
test2.push_back("hello world");
You can learn a lot about char*/char[] in your favorite book on C (not on C++, because C++ provides much better facilities for representing strings than C does).
The declaration/assignment
char *test = "hello world";
should be
const char *test = "hello world";
because string literals are pointers to constants. If you want a vector of strings in C++, you do it like this:
std::vector<std::string> test2;
test2.push_back("hello world");
This works, because string literals can be implicitly converted to std::string.
So the thing to remember is the difference between a pointer to a value and the value itself.
The value itself is the literal value that a variable represents as stored in memory.
A pointer is the address in memory that some value is stored at.
Pointers are useful because they allow you to access, change, and preserve changes in information across multiple functions / methods, which comes in handy when you realize you can only return one value from any function, but sometimes you want a lot more information than that.
The thing about arrays is that, while a lot of people don't realize this when first learning C++, they are pointers. A[0] isn't a variable, it's a pointer to a memory address. Arrays are handy because when declaring an array, you segment off a portion of memory reserved for use for that array. This is useful because it allows you to access the values stored in that block of memory very very quickly.
So really, there's not that much difference between declaring a pointer (char*) and an array (char[]) other than that the pointer will refer to a single location in memory while the array will refer to set of contiguous locations in memory.
To learn more about pointers and how to use them properly, visit http://www.cplusplus.com/doc/tutorial/pointers/ .
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm really confused about this because personally, I come from a java background, and recently began c++. So, I learnt all the basic stuff, like, printing stuff out to the screen and whatnot, and now, I learnt POINTERS. So, the person on youtube (The Cherno's C++ Pointer tutorial This was not the video where he declared the const char*, just the pointer tutorial that I followed.) I've been following was using this following statement to declare what I know as a 'string'.
const char* str = "random text here";
But, how is a char* converted into a string, and its even using the double quotation marks like a string! Also, what does a constant have to do with any of this? If I remove the const from my code it gives me an error. But, I understand what a pointer is. It is a variable that holds the memory address of another variable, so if one was to access that variable directly, they would just have to do *ptrVarName and dereferenced it. But how can a string "like this one" be a memory address?
Wouldn't I have to do something like this?
char[] str = "string here";
and THEN do:
char* stringPointer = *str;
(WARNING: untested code!)
Thanks in advance.
(oh and sorry if this is a really NOOBY question or the question is poorly constructed, I've just started out with c++ and stackoverflow)
EDIT: Ok, so I understand what the char* str means. It means that when you reference *str, it means that you're accessing the first character in memory. Ok, I get it now. But, what does const mean?
const char* str = "random text here";
On the right hand side, the "random text here" defines a string literal which actually is an array of type const char[17] (including the null terminator character). When you assign that array to const char* str it decays to a pointer that points to the first character. You cannot modify the string literal through the pointer because string literals are stored in read-only memory, so the following would be illegal: str[0] = 'x';
char[] str = "string here";
This one is different. It defines the char array str which has the same size as the string literal on the right hand side (const char[12]). The string literal will be copied into the array str, so you will be able to modify str. In this case, it would be legal to write str[0] = 'x';.
If you declare const char* sth ="mystring"
It will place mystring inthe memory and sth pointing to that its work like array but with direct access to memory
These are plain C-strings. A C string is always null terminated. In other words- it has '\0' at the end. So you need only the place in memory where the string starts and you can find when it ends.
For pointer arithmetic these [] brackets are only syntax sugar. str[] is the same as *str and str[1] is the same as *(str+1) only incrementing the pointer by one char (8 bits) and getting the address of the second element.
C doesn't really have strings. A string is an array of characters, terminated by a nul (0). Now arrays and pointers in C are closely linked, and a char * or const char * usually points to a string, but only in the same way as other pointers usually point to arrays. An individual char * might only point to a single character, you have to know from context, just as an int * might point to one integer or an array of integers.
Because strings are handy, there's a special syntactical rule for strings literal. A string literal in quotes becomes a const char * (in fact its type is char * for backwards compatibility). So in this sense, C has strings. But all that is happening is that the string is being laid out in the data section of the program, then its address taken.
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 5 years ago.
I've run into a strange, and very specific issue. As some background, I need to support some legacy code that's passing around a lot of large c-style strings. Since these get pretty gigantic, I want to avoid unnecessarily copying that data, which would include copy constructing std::strings just for one operation.
I want to use std::sort on these strings, but they obviously lack iterators. However, according to the documentation for std::sort, I should just be able to pass in two pointers for any contiguous random access memory, but it isn't working with my c-style string
Basically it's like this:
char* foo = "test string";
std::sort(foo, foo + 11); // access violation occurs
However:
char foo[] = "test string";
std::sort(foo, foo + 11); // perfect fine, sorted correctly
This is extra confusing to me, because as far as I know, char* and char[] are essentially the same. Why does char* break, while char[] succeeds? How can I pass a c-style string into an STL algorithm?
char* foo = "test string";
This is a pointer to a string literal, which is stored in read-only memory, thus you cannot modify/sort it.
Your code should be giving you a warning, similar to this:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp
main.cpp:3:17: warning: conversion from string literal to 'char *' is deprecated
[-Wc++11-compat-deprecated-writable-strings]
char* foo = "test string";
^
Please read: What is the difference between char s[] and char *s?
This question already has answers here:
How to initialize all members of an array to the same value?
(26 answers)
Closed 8 years ago.
I have been wondering, why can I not write my code like so:
char myChar[50];
myChar = "This is a really cool char!";
Or at least like this:
char myChar[50];
myChar[0] = "This is a really cool char!";
The second way makes more sense that it should work, to me, seeing that I would
start the array at the point I want it to start moving the letters into each spot in the
array.
Does anyone know why C++ does not do this? And can you show me the reasoning behind the
right way to do it?
Thank you all in advance!
The first line:
char myChar[50];
...allocates an array of 50 characters on the stack. The second line:
myChar = "This is a really cool char!";
Is attempting to assign a const static string (which exists in read-only memory in the text segment of your code) to the address of the beginning of the array. This is an incompatible LVALUE/RVALUE matcing/assignment. This approach:
const char* myChar = "This is a really cool char";
Will work, as the assignment of a pointer to address a string literal must be done at initialization time. There are potential exceptions, as in assigning a const char* pointer to a string literal like so:
/*******************************************************************************
* Preprocessor Directives
******************************************************************************/
#include <stdio.h>
/*******************************************************************************
* Function Prototypes
******************************************************************************/
const char* returnErrorString(int iError);
/*******************************************************************************
* Function Definitions
******************************************************************************/
int main(void) {
int i;
for (i=(-1); i<3; i++) {
printf("i=%d - Error String:%s\n", returnErrorString(i));
}
return 0;
}
const char* returnErrorString(int iError) {
const char* ret = NULL;
switch (iError) {
case 0:
ret = "No error";
break;
case (-1):
ret = "Invalid input";
break;
default:
ret = "Unknown error";
break;
}
return ret;
}
You might benefit from reading the post in my references below. It will give you some info on how code, variables, constants, etc, are broken into different segments of the final binary, and why some approaches don't even make sense. Also, it would be beneficial to read up a bit on terminology like integer literals, string literals, l-values, r-values, etc.
Good luck!
References
Difference between declared string and allocated string, Accessed 2014-05-01, <https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string>
You must initialise the array of chars inside the declaration of the array. There is actually no reason for not doing so, as if not, your array will contain garbage values until you initialise it. I advise you to look at this link:
Char array declaration and initialization in C
Also, you are allocating a char array of size 50 but only using 28 elements of it, this would appear to me to be a waste...
Try the following for simple string initialisations:
char mychar[11] = "hello world";
Or...
char *mychar = "hello world";
I hope this helps...
If you want to think of this in holistic terms, the reason is because myChar isn't a string -- it's just an array of char. Hence "FooGHBar" and char [50] are completely different types. Related in a sense, but really not.
Now some might say, "but "FooBar" is a string, and char [50] is really just a string too." But that is going on the assumption that myChar is the same as "FooBar", and it's not. It's also assuming that the compiler understands that both char[50] and char* are pointers to strings. The compiler doesn't understand that. There could be any manner of thing stored in those places that have nothing to do with strings.
"But myChar is just a pointer?"
That is the reason why people think that the assignment should be a natural thing -- but the fundamental premise is wrong. myChar is not a pointer. It is an array. A name which refers to an array will decay into a pointer at the drop of a hat, but an array is not a pointer.
This question already has answers here:
Assigning char array a value in C
(2 answers)
Closed 8 years ago.
I get no error when I type
char a[10] = "Hi";
But when I change it to the following, I get an error: Array type char is not assignable.
char a[10];
a = "Hi";
Why is array type char not assignable? Is it because the language is written that way on purpose or am I missing a point?
An array is not a modifiable lvalue
use
char a[10];
strcpy(a, "Hi");
The C++ way of doing this, as I commented above, would be to use std::string instead of char[]. That will give you the assignment behavior you're expecting.
That said, the reason you're only getting an error for the second case is that the = in these two lines mean different things:
char a[10] = "Hi";
a = "Hi";
The first is an initialization, the second is an assignment.
The first line allocates enough space on the stack to hold 10 characters, and initializes the first three of those characters to be 'H', 'i', and '\0'. From this point on, all a does is refer to the position of the the array on the stack. Because the array is just a place on the stack, a is never allowed to change. If you want a different location on the stack to hold a different value, you need a different variable.
The second (invalid) line, on the other hand, tries to change a to refer to a (technically different) incantation of "Hi". That's not allowed for the reasons stated above. Once you have an initialized array, the only thing you can do with it is read values from it and write values to it. You can't change its location or size. That's what an assignment would try to do in this case.
The language does not allow assigning string literals to character arrays. You should use strcpy() instead:
strcpy(a, "Hi");
a is a pointer to the array, not the array itself. It cannot be reassigned.
You tagged with C++ BTW. For that case better use std::string. It's probably more what you're expecting.
Simple, the
char a[10] = "Hi";
is a little "extra feature", as it cannot be done like that on run-time.
But that's the reason for C/C++ standard libraries.
#include <string.h>
// ...
strcpy(a,"Test"); // STR-ing C-o-PY.
This comes from the C's standard library. If using C++ you should use std::string, unless you really want to suck all the possible performance from your destination PC.
this is because initialization is not an assignment. the first thing which works is an initialization, and the second one, which does not work, as expected, is assignment. you simply cant assign values to arrays you should use sth like strcpy or memcpy. or you can alternatively use std::copy from <algorithm>
It is so simple,(=) have two different mean assignment and initialization. You can also write your code like that
#include <iostream>
using namespace std;
int main ()
{
char message[3] = {'H', 'i', '\0'};
cout << message<< endl;
return 0;
}
in this code you have no need to write a difficult code or function and even no need of string.h
Been thinking, what's the difference between declaring a variable with [] or * ? The way I see it:
char *str = new char[100];
char str2[] = "Hi world!";
.. should be the main difference, though Im unsure if you can do something like
char *str = "Hi all";
.. since the pointer should the reference to a static member, which I don't know if it can?
Anyways, what's really bugging me is knowing the difference between:
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
So, would be much appreciated if anyone could tell me the difference? I have a hunch that both might be compiled down the same, except in some special cases?
Ty
Let's look into it (for the following, note char const and const char are the same in C++):
String literals and char *
"hello" is an array of 6 const characters: char const[6]. As every array, it can convert implicitly to a pointer to its first element: char const * s = "hello"; For compatibility with C code, C++ allows one other conversion, which would be otherwise ill-formed: char * s = "hello"; it removes the const!. This is an exception, to allow that C-ish code to compile, but it is deprecated to make a char * point to a string literal. So what do we have for char * s = "foo"; ?
"foo" -> array-to-pointer -> char const* -> qualification-conversion -> char *. A string literal is read-only, and won't be allocated on the stack. You can freely make a pointer point to them, and return that one from a function, without crashing :).
Initialization of an array using a String literal
Now, what is char s[] = "hello"; ? It's a whole other thing. That will create an array of characters, and fill it with the String "hello". The literal isn't pointed to. Instead it is copied to the character-array. And the array is created on the stack. You cannot validly return a pointer to it from a function.
Array Parameter types.
How can you make your function accept an array as parameter? You just declare your parameter to be an array:
void accept_array(char foo[]);
but you omit the size. Actually, any size would do it, as it is just ignored: The Standard says that parameters declared in that way will be transformed to be the same as
void accept_array(char * foo);
Excursion: Multi Dimensional Arrays
Substitute char by any type, including arrays itself:
void accept_array(char foo[][10]);
accepts a two-dimensional array, whose last dimension has size 10. The first element of a multi-dimensional array is its first sub-array of the next dimension! Now, let's transform it. It will be a pointer to its first element again. So, actually it will accept a pointer to an array of 10 chars: (remove the [] in head, and then just make a pointer to the type you see in your head then):
void accept_array(char (*foo)[10]);
As arrays implicitly convert to a pointer to their first element, you can just pass an two-dimensional array in it (whose last dimension size is 10), and it will work. Indeed, that's the case for any n-dimensional array, including the special-case of n = 1;
Conclusion
void upperCaseString(char *_str) {};
and
void upperCaseString(char _str[]) {};
are the same, as the first is just a pointer to char. But note if you want to pass a String-literal to that (say it doesn't change its argument), then you should change the parameter to char const* _str so you don't do deprecated things.
The three different declarations let the pointer point to different memory segments:
char* str = new char[100];
lets str point to the heap.
char str2[] = "Hi world!";
puts the string on the stack.
char* str3 = "Hi world!";
points to the data segment.
The two declarations
void upperCaseString(char *_str) {};
void upperCaseString(char _str[]) {};
are equal, the compiler complains about the function already having a body when you try to declare them in the same scope.
Okay, I had left two negative comments. That's not really useful; I've removed them.
The following code initializes a char pointer, pointing to the start of a dynamically allocated memory portion (in the heap.)
char *str = new char[100];
This block can be freed using delete [].
The following code creates a char array in the stack, initialized to the value specified by a string literal.
char [] str2 = "Hi world!";
This array can be modified without problems, which is nice. So
str2[0] = 'N';
cout << str2;
should print Ni world! to the standard output, making certain knights feel very uncomfortable.
The following code creates a char pointer in the stack, pointing to a string literal... The pointer can be reassigned without problems, but the pointed block cannot be modified (this is undefined behavior; it segfaults under Linux, for example.)
char *str = "Hi all";
str[0] = 'N'; // ERROR!
The following two declarations
void upperCaseString(char *_str) {};
void upperCaseString(char [] _str) {};
look the same to me, and in your case (you want to uppercase a string in place) it really doesn't matters.
However, all this begs the question: why are you using char * to express strings in C++?
As a supplement to the answers already given, you should read through the C FAQ regarding arrays vs. pointers. Yes it's a C FAQ and not a C++ FAQ, but there's little substantial difference between the two languages in this area.
Also, as a side note, avoid naming your variables with a leading underscore. That's reserved for symbols defined by the compiler and standard library.
Please also take a look at the http://c-faq.com/aryptr/aryptr2.html The C-FAQ might prove to be an interesting read in itself.
The first option dynamically allocates 100 bytes.
The second option statically allocates 10 bytes (9 for the string + nul character).
Your third example shouldn't work - you're trying to statically-fill a dynamic item.
As to the upperCaseString() question, once the C-string has been allocated and defined, you can iterate through it either by array indexing or by pointer notation, because an array is really just a convenient way to wrap pointer arithmetic in C.
(That's the simple answer - I expect someone else will have the authoritative, complicated answer out of the spec :))