When to use const char * and when to use const char []
Both are distinctly different, For a start:
- The First creates a pointer.
- The second creates an array.
Read on for more detailed explanation:
The Array version:
char text[] = "text";
Creates an array that is large enough to hold the string literal "text", including its NULL
terminator. The array text
is initialized with the string literal "text".The array can be modified at a later time. Also, the array's size is known even at compile time, so sizeof
operator can be used to determine its size.
The pointer version:
char *text = "text";
Creates a pointer to point to a string literal "text". This is faster than the array version, but string pointed by the pointer should not be changed, because it is located in an read only implementation defined memory. Modifying such an string literal results in Undefined Behavior.
In fact C++03 deprecates use of string literal without the const
keyword. So the declaration should be:
const char*text = "text";
Also,you need to use the strlen()
function, and not sizeof
to find size of the string since the sizeof
operator will just give you the size of the pointer variable.
Which version is better?
Depends on the Usage.
- If you do not need to make any changes to the string, use the pointer version.
- If you intend to change the data, use the array version.
EDIT: It was just brought to my notice(in comments) that the OP seeks difference between:
const char text[]
and const char* text
Well the above differing points still apply except the one regarding modifying the string literal. With the const
qualifier the array test
is now an array containing elements of the type const char
which implies they cannot be modified.
Given that, I would choose the array version over the pointer version because the pointer can be(by mistake)easily reseated to another pointer and the string could be modified through that another pointer resulting in an UB.
const char myVar* vs. const char myVar[]
The pointer can be reassigned, the array cannot.
const char* ptr = "Hello World!";
const char arr[] = "Hello World!";
ptr = "Goodbye"; // okay
arr = "Goodbye"; // illegal
Also, as others have said:
sizeof(ptr) == size of a pointer, usually 4 or 8
sizeof(arr) == number of characters + 1 for null terminator
How do you declare string constants in C?
There's one more (at least) road to Rome:
static const char HELLO3[] = "Howdy";
(static
— optional — is to prevent it from conflicting with other files). I'd prefer this one over const char*
, because then you'll be able to use sizeof(HELLO3)
and therefore you don't have to postpone till runtime what you can do at compile time.
The define has an advantage of compile-time concatenation, though (think HELLO ", World!"
) and you can sizeof(HELLO)
as well.
But then you can also prefer const char*
and use it across multiple files, which would save you a morsel of memory.
In short — it depends.
How to read from - unsigned char const * when use Media Foundation?
You can't cut corners like this:
unsigned char const * pData;
...
hr = MFCreateMFByteStreamOnStreamEx((IUnknown*)pData, &spByteStream);
IUnknown
is not yet another fancy alias for a byte. You are supposed to literally supply interface pointer representing stream, as documented.
Media Foundation does offer you means to read from memory bytes. You need to create a create a real stream, IStream
or IRandomAccessStream
or IMFByteStream
per docuemntation. Also supply IMFAttributes
you created with proper attributes to specify data type (which otherwise in the case of a file are derived from extension or MIME type) and then Source Reader API would be able to process memory bytes as source of media file data, and suitable decoder would decode audio into PCM data (similar to this).
Something you can do real quick: CreateStreamOnHGlobal
to create IStream
implementation and copy your bytes into underlying buffer (see docs). Then MFCreateMFByteStreamOnStream
would create a IMFByteStream
wrappr over it, and you can use this wrapper as MFCreateSourceReaderFromByteStream
argument.
Do these statements about pointers have the same effect?
No.
char str1[] = "Hello world!"; //char-array on the stack; string can be changed
char* str2 = "Hello world!"; //char-array in the data-segment; it's READ-ONLY
The first example creates an array of size 13*sizeof(char)
on the stack and copies the string "Hello world!"
into it.
The second example creates a char*
on the stack and points it to a location in the data-segment of the executable, which contains the string "Hello world!"
. This second string is READ-ONLY.
str1[1] = 'u'; //Valid
str2[1] = 'u'; //Invalid - MAY crash program!
Behavior of `swprintf` when passed a `char const*` matching a `L%s` specifier
Note that from swprintf of MSDN:
swprintf is a wide-character version of sprintf; the pointer arguments to swprintf are wide-character strings.
and then in the example:
wchar_t buf[100];
int len = swprintf( buf, 100, L"%s", L"Hello world" );
so at least Microsoft documented this.
And then in the page of format specifiers
s String When used with printf functions, specifies a single-byte–character string; when used with wprintf functions, specifies a wide-character string. Characters are printed up to the first null character or until the precision value is reached.
And then
S String When used with printf functions, specifies a wide-character string; when used with wprintf functions, specifies a single-byte–character string. Characters are printed up to the first null character or until the precision value is reached.
So what you want is upper-case %S
.
See even this similar question: visual studio swprintf is making all my %s formatters want wchar_t * instead of char * where they suggest using %ls
(always consider the parameter wchar_t*
) and %hs
(always consider the parameter char*
)
When to use & when reading an input
The parameters passed to scanf
after the first one are all addresses. You need to provide the address of the variable to assign the value of the input.
That's why, when you read the value of a variable, you have to pass its address using the &
operator.
For example,
int n;
scanf("%d", &n);
You can also assign the variable's address address to a pointer and use that:
int n;
int *p = &n;
scanf("%d", p);
In case of arrays, the array's name is actually the base address, i.e. address of the first element. You can use that in scanf
too:
int arr[4];
scanf("%d", arr); // the input value will be stored in a[0]
scanf("%d", &arr[0]); // does the exactly same thing as the statement above
scanf("%d", &arr[1]); // reads the input into a[1]
scanf("%d", a + 1); // does the same as above
This way is useful for reading strings without spaces from input:
char str[64];
scanf("%s", str);
Related Topics
Undefined Reference to Mempcy@Glibc_2.14 When Compiling on Linux
In Which Access Control Context Are Concepts Evaluated
Ordering of Using Namespace Std; and Includes
Uniform Initialization Fails to Copy When Object Has No Data Members
How to Include Data Object Files (Images, etc.) in Program and Access the Symbols
How to Parse CSV Using Boost::Spirit
Dependent Name Resolution & Namespace Std/Standard Library
C++ Regex for Overlapping Matches
C++: Where Does the Ofstream Class Save the Files To
Why Do Two Functions Have the Same Address
Why Can't I Use a "Break" Statement Inside a Ternary Conditional Statement in C++
C++ When Is It Ok to Extend the 'Std' Namespace
C++ - Std::Thread Crashes Upon Execution
Undefined Symbol on a Template Operator Overloading Function