Character Pointers and Integer Pointers (++)

Character pointers and integer pointers (++)

Simple, in the provided scenario:

  • char is 1 byte long
  • int (in your platform) is 4 bytes long

The ++ operator increments the pointer by the size of the pointed type.

C string pointer. int pointer vs char pointer

Why 'k'?

You declare:

char name[] = "john q public";

On access, name is converted to a pointer to the first element (a pointer to 'j') C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)

You assign:

int *p = name;

So p holds as its value the memory location (the address) where 'j' is stored (e.g. p points to 'j'). Then you print printf("%c\n", *p+1); where derefereing p (e.g. *p) is the character 'j' and by ASCII Table and Description, j + 1 == k, so your output of 'k' is completely expected.

j ucem n 1??

You declare int *p, Pointer Type Controls Pointer Arithmetic. So p++ advances p by sizeof(int) bytes (typically 4-bytes) instead of sizeof(char) bytes (1-byte). So lets look at:

    john q public
-------------
0123456789012
^ ^ ^ ^ 4-bytes per p++
|
p

Incrementing by 4-bytes you have j uc... where ... indicates where you invoke Undefined Behavior by accessing memory beyond the end of the name array -- all bets are off.

Always Compile With Warnings Enabled

Always compile with warnings enabled, and do not accept code until it compiles without warning. To enable warnings add -Wall -Wextra -pedantic to your gcc/clang compile string (also consider adding -Wshadow to warn on shadowed variables). For VS (cl.exe on windows), use /W3. All other compilers will have similar options. Read and understand each warning -- then go fix it. They will identify any problems, and the exact line on which they occur. You can learn a lot by listening to what your compiler is telling you.

Had you compiled with warnings enabled, you would have found:

warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
int *p = name;

Dereferencing an int pointer vs char pointer

In this code snippet

int a = 5;
int *b = &a;
*b = 6;

the last assignment stores the integer constant to the object pointed to by the pointer b. That is the value of the object a is changed not the value (address) stored in the pointer b.

In this code snippet

char *name = "test";
name = "test2";

the value of the pointer itself is changed not the object pointed to by the pointer. So at first the pointer name pointed to the first character of the string literal "test" and then it is reassigned to point to the first character of the string literal "test2".

It is the similar to the following code

int a = 5;
int *b = &a;

int a2 = 6;
b = &a2;

If you want to change an object pointed to by a pointer of the type char * you could write

char s[] = "test";
char *name = s;
*name = 'T';

In this case the array s will have "Test".

Pay attention that you may not change a string literal. That is if instead of the array s you will write

char *s = "test";
char *name = s;
*name = 'T';

then the code will have undefined behavior.

Also bear in mind that in this declaration

char *s = "test";

the string literal having the type char[5] is implicitly converted to pointer to its first element.

casting int pointer to char pointer

By casting a integer pointer to a char pointer, will they both contain the same address?

Both pointers would point to the same location in memory.

Does the cast operation change the value of what the char pointer points to?

No, it changes the default interpretation of what the pointer points to.

When you read from an int pointer in an expression *myIntPtr you get back the content of the location interpreted as a multi-byte value of type int. When you read from a char pointer in an expression *myCharPtr, you get back the content of the location interpreted as a single-byte value of type char.

Another consequence of casting a pointer is in pointer arithmetic. When you have two int pointers pointing into the same array, subtracting one from the other produces the difference in ints, for example

int a[20] = {0};
int *p = &a[3];
int *q = &a[13];
ptrdiff_t diff1 = q - p; // This is 10

If you cast p and q to char, you would get the distance in terms of chars, not in terms of ints:

char *x = (char*)p;
char *y = (char*)q;
ptrdiff_t diff2 = y - x; // This is 10 times sizeof(int)

Demo.

What is the difference in pointers when defining char and int?

"Something"

is essentially short for:

static const char some_hidden_array[] = {'S', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'};
some_hidden_array

That is, when you write "Something", the compiler generates an array behind the scenes, and gives you a pointer to the start of that array. Since this is already a pointer to a char, you'll have no problem assigning it to a variable of type "pointer to a char" (written as char*).

10

is not short for anything similar. It's just the number 10 - it's not a pointer to an array containing the number 10, or anything like that.

Note that a char is a single character, not a string, which is why the string syntax is unusual compared to most other types - a string is several chars, not just one. If you try to use a plain old char, you'll see the same thing:

char *myChar = 'a'; // error

or for any other type:

float *myFloat = 42.1f; // error

In other words, it's not strange that 10 gives an error - if anything, it's strange that "Something" doesn't. (At least, it's strange until you know how string literals work)

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