When to Use Const Char * and When to Use Const Char []

When to use const char * and when to use const char []

Both are distinctly different, For a start:

  1. The First creates a pointer.
  2. 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



Leave a reply



Submit