Difference Between Using Character Pointers and Character Arrays

What is the difference between char array and char pointer in C?

char* and char[] are different types, but it's not immediately apparent in all cases. This is because arrays decay into pointers, meaning that if an expression of type char[] is provided where one of type char* is expected, the compiler automatically converts the array into a pointer to its first element.

Your example function printSomething expects a pointer, so if you try to pass an array to it like this:

char s[10] = "hello";
printSomething(s);

The compiler pretends that you wrote this:

char s[10] = "hello";
printSomething(&s[0]);

Difference between using character pointers and character arrays

Please go through this article below:

Also see in case of array of char like in your case, char new_str[] then the new_str will always point to the base of the array. The pointer in itself can't be incremented. Yes you can use subscripts to access the next char in array eg: new_str[3];

But in case of pointer to char, the pointer can be incremented new_str++ to fetch you the next character in the array.

Also I would suggest this article for more clarity.

Is a char array more efficient than a char pointer in C?

When discussing performance in general, allocation, access time and copy time separate things. You seem mostly concerned about allocation.

But there are lots of misconceptions here. Arrays are used for storing. Pointers are used to point at things stored elsewhere. You cannot store any data in a pointer, you can only store an address to data allocated elsewhere.

So comparing pointers or arrays is pretty much nonsense, because they are separate things. Similar to "should I live in my house at a street address or should I live in the sign stating my street address".

I understand that using char* gives a pointer to the first character in str1

No, it gives a pointer to a single character which is allocated somewhere else. Though it doesn't point anywhere meaningful until you assign an address to it. In case of arrays, it will typically get set to point at the first character of the array.

I recall that in some encodings it can be more

No, a character is per definition always 1 byte. Some exotic systems might have 16 bits per bytes or such though. This is of no concern unless you program exotic DSPs and the like. As for other character encodings, there's wchar_t which is a different topic entirely.

whereas in the case of char* we're really just saying allocate a pointer to a single byte

No, we tell it to allocate room for the pointer itself. Which is typically of a size between 2 to 8 bytes depending on address bus width of the specific system.

But what happens if the string we assign to str1 is more than a single byte, how is that allocated?

However you like. You can assign it to a read-only string literal, or a static storage duration variable, or a local automatic storage variable, or dynamically allocated variables. The pointer itself doesn't know or care.

How much more work is needed to appropriately allocate that?

It depends on what you want to allocate.

Because of the uncertainty from the compiler's point of view when dealing with char pointers

What uncertainty is that? Pointers are pointers and the compiler don't treat them much differently than other variables.

is it more efficient to use a char array when I either know the length ahead of time or want to limit the length to start with?

You need to use an array, because data cannot be stored in thin air. Again, data cannot be stored "in pointers".

What the memory difference between char *array and char array[]?

char tmp[] = "hello"; is an array of 6 characters initialized to "hello\0" (it has automatic storage duration and resides within the program stack).

char *tmp = "hello"; is a pointer to char initialized with the address for the string literal "hello\0" that resides in readonly memory (generally within the .rodata section of the executable, readonly on all but a few implementations).

When you have char tmp[] = "hello";, as stated above, on access the array is converted to a pointer to the first element of tmp. It has type char *. When you take the address of tmp (e.g. &tmp) it will resolve to the same address, but has a completely different type. It will be a pointer-to-array-of char[6]. The formal type is char (*)[6]. And since type controls pointer arithmetic, iterating with the different types will produce different offsets when you advance the pointer. Advancing tmp will advance to the next char. Advancing with the address of tmp will advance to the beginning of the next 6-character array.

When you have char *tmp = "hello"; you have a pointer to char. When you take the address, the result is pointer-to-pointer-to char. The formal type is char ** reflecting the two levels of indirection. Advancing tmp advances to the next char. Advancing with the address of tmp advances to the next pointer.

Difference between char array and pointer to char array

The first byte of the first element in the array is at the same place as the first byte of the array, because they are the same byte.

Most C implementations use the memory address, or some representation of it, of the first byte of an object as a pointer to the object. The array contains its elements, and there is no padding: The first element of the array starts where the array starts. So the first byte in the first element is the first byte in the array. So they have the same memory address.

There is a rule in C that converting a pointer to an object to a char * produces a pointer to the first byte of an object (C 2018 6.3.2.3 7). So, given an array a, (char *) &a[0] is a pointer to the first byte of the first element, and (char *) &a is a pointer to the first byte of the array. These are the same byte, so (char *) &a[0] == (char *) &a.

However, &a[0] and &a have different types. If you attempt to compare them directly with &a[0] == &a, the compiler should issue a warning that the types do not match.

If you pass &a as an argument to a routine that expects &a[0], it will often work in most modern C implementations because they use plain memory addresses as pointers, so &a is represented with the same bits (a memory address) as &a[0], so the receiving routine gets the value it expected even though you passed a pointer of the wrong type. However, the behavior of your program will not be defined by the C standard, since you have violated the rules. This was more of a problem in older C implementations when memory models were not simple flat address spaces, and different types of pointers may have had different representations.

Difference between char pointer and char array

There are many differences between pointers and arrays, but the reason you are getting garbage, is that by the time you use ptr with an index, it already points to the null terminator of "12345".

Everytime you do this:

*ptr++;

ptr points to the next element it used to point (i.e. 1, 2, 3, ...). When the loop ends, it points to the null terminator \0 and then when you try to index it with i, it points to unknown memory.

I suggest you use a temp pointer to iterate through the elements instead:

const char* ptr; // declaring ptr constant in this case is a good idea as well

...

ptr = "12345";
char *tmp = ptr;

...

while(*tmp != 0)
cout << *tmp++ << endl;

What are the differences between char* and all other types of pointers in C?

Let's go through each of your questions one by one.

Printing

In your first code snippet, you show that printf is capable of printing strings. Of course it printed a string. You gave it a %s which is meant to be a string. But first, what is a string? To explain that, we need to understand arrays and chars.

What's a String?

First, what's a char? A char is a singular character (or an 8-bit number, but for our purposes it's a character). A character can be a letter (a, b, c)m or any other symbol (?, !, ., numbers, there are also some control characters). Typically, if you only needed one character, you'd declare it like this:

char letter_a = 'a';

So what is an array? An array is a group of values all next to each other. Consider the following code:

int int_array[] = int[50];
int_array[0] = 1;
int_array[1] = 2;
...

In this example, what is int_array? The answer seems obvious. It's an array. But there's more to it than thar. What if we do this?

printf("%d\n", *int_array);

It prints out 1. Why? Because int_array is actually just a pointer to the first element of the array.

So why am I talking about arrays? Because a string is just an array of characters. When you run char* string = "Hello!", you just create an array that looks like this: ['H', 'e', 'l', 'l', 'o', '!', '\0']. C knows that the string has ended once it reaches the null symbol ('\0').

In your first snippet, var is a pointer to the letter 'H', and the print statement keeps printing characters until it reaches null.

What about the second snippet?

%d doesn't dereference the variable like %s does. It just prints a number as a signed integer. The integer in this case is the memory address of your integer.

Why cant you assign pointers?

You can. You'll get a warning, and it will probably cause a segmentation fault, but you can try it. I compiled your code example using clang and this is what I got:

test.c:1:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
void main() {
^
test.c:1:1: note: change return type to 'int'
void main() {
^~~~
int
test.c:2:7: warning: incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int' [-Wint-conversion]
int* var = 5;
^ ~
2 warnings generated.

I will not dare try to run it though. Basically what you just did is try to access the fifth location in memory, which is most likely some OS stuff. You don't have access to that

Why did it work for the string?

Because it doesn't point to a specific location. It points to the location of the string that C made for you. Your code is roughly equivalent to this:

char h = 'H';
char e = 'e';
...
char* var = &h;


Related Topics



Leave a reply



Submit