-2

I m new to programming, there is some part that made me confuse when learning pointer.

code1:

int main()
{
    char string[]="hello";

    char *my_pointer=string;

    printf("first character is %c", *my_pointer);
    return 0;
}

output : first character is h

code 2:

int main()
{    
    char array_of_words[]="one\0two\0three";

    char *my_pointer=array_of_words;

    printf("%s \n",my_pointer);

    return 0;
}

output : one

questions:

I'm confuse here, the printf function part in the first code using asterisk symbol means to point what is inside pointer (my_pointer) which is the address of variable string that refer to the pointer string for an array that point the memory address of the first word in array "hello". is my understanding true?

and also when I change %c in printf("first character is %c", *my_pointer); to %s, the program crash. i want to know why i cant use %s and what is the different if i dont use asterisk in my_pointer in printf("first character is %c", my_pointer);

While in second code my_pointer variable didnt use asterisk(*) in {printf("%s \n",my_pointer);}. in this code is my_pointer refer to the address of array_of_words variable or what is inside of my_pointer? and also why the output is 'one' not 'o'?

Shiva
  • 11,485
  • 2
  • 67
  • 84
fiksx
  • 176
  • 1
  • 15

4 Answers4

6

C strings, arrays, and pointers can be very confusing. Let's look at what each of them is.

A pointer refers to an address in memory. You seem somewhat familiar with them. Think of it like a locker key - it tells you a place in memory where you can store data.

When you declare an array, the compiler sets off a region of memory to store it. The variable that you called the array can be treated as a pointer to the start of that data. For example, *string is the first element of the string.

Now let's apply that to your programs.

Both your programs create a string and set my_pointer to the memory address that the string starts at. my_pointer=string means "Copy the contents of the variable string (which decays to the address of the start of the string) into my_pointer."

In program 1, read *my_pointer as "The contents of the memory address that my_pointer points to." Since my_pointer points at the first element of the string, that is the character h.

Why then does it crash when you substitute %s? Because printf needs a pointer to the string so it can go through the whole array. Since C is copy-by-value, giving it the value of first element is pointless since it can't get at any of the others. As a result, printf tries to read a character as a memory address, which fails. A good compiler might see that and give you a warning.

Now program 2. my_pointer refers to the address of the string in memory, not the address of the variable array_of_words.The output is one because printf prints everything up to the first null character (\0). Since the first null is right after one, it prints one and then hits the null and stops.

anonymoose
  • 819
  • 2
  • 11
  • 25
  • Thanks for the detailed explanation!! In program 2, still need some clarification! my pointer that you mention refer to the address of the string is the one one inside printf if? And 'string' that you mention refer to one\0two\0three? Char array_of_words[]="one\0two\0three"->array_of_words is pointer that point 'o' right? And *my_pointer=array_of_words means copy what is inside memory address of array_of_words ='o' to my_pointer then printf("%s\n",my_pointer) ->why not it print 'o'?? – fiksx May 06 '17 at 17:55
  • @DevinaMuljono `*my_pointer=array_of_words` copies the _address_ of the first element of the contents of `array_of_words` into `my_pointer`. It does not copy the first element, it copies its address. So `*my_pointer == my_pointer[0] == 'o'`, but `strcmp(my_pointer, "one") == 0` is true. (`strcmp()` compares two strings and returns 0 if they contain the same string - for example, it returns 0 for "abc" and "abc". – anonymoose May 06 '17 at 18:38
  • *my_pointer=array_of_words copies the address of first element of the content of array_of_the_words into my_pointer but why in printf (%s\n,my_pointer) produce 'one' not 'o'? Is it because my_pointer in printf refer to the memory address?? – fiksx May 07 '17 at 11:22
  • Oops. I made a mistake in the first sentence of my earlier comment. First, I have to say that the code `char *my_pointer = array_of_words;` is the same as `char *my_pointer; my_pointer=array_of_words;`. (`*my_pointer=array_of_words` is invalid syntax unless my_pointer is of type `char**`. Then it's valid because `*my_pointer` yields a char pointer.) `my_pointer=array_of_words;` copies the address of the first character of the string into `my_pointer`. As for your question, yes, `my_pointer` refers to the string's memory address. That's the whole point of pointers. – anonymoose May 07 '17 at 12:08
  • Thankyou but still confuse on some point!! So char *my_pointer=array_of_the_words is valid because it yield char pointer which is copy the string's first character address right?? So inside of it is 'o'??? But why printf(%s\n , my pointer) not produce 'o' instead produce 'one'???? – fiksx May 07 '17 at 12:39
  • @DevinaMuljono That's not how C pointers and strings work. `my_pointer=array_of_words` (or `char *my_pointer = array_of_words;`) finds the address that the string referred to by `array_of_words` starts at and copies the address into `my_pointer`. `printf` is able to print the whole string because if you know that a string starts at a certain point in memory, you can find any character in that string by taking the address of the string's start plus n. `my_pointer[n]` actually evaluates to `*(my_pointer + n)`, which means "the character n characters ahead of the start of the string." – anonymoose May 07 '17 at 14:40
  • is this means that (char *my_pointer=array_of_the_words ) actually copy the address of whole character (one/0two/0three) but only copy the address of first character because it is character type(?) so if i refer to *my_pointer which is the value inside it,it produce 'o' because its copy the address of the the first string and.m because its char type (?) while my_pointer refer to the memory address and in printf can print whole string by plus n(?) – fiksx May 07 '17 at 14:58
  • After you say `my_pointer=array_of_words`, you can use `my_pointer` anywhere you would use `array_of_words` (though there's probably an exception to that) until you reassign `my_pointer`. If you're still lost, you can find a lot of tutorials and documentation with a simple google search. I think that [this page on pointers](http://www.tutorialspoint.com/cprogramming/c_pointers.htm) (and that site's pages on arrays and strings) may help. – anonymoose May 07 '17 at 15:03
  • @DevinaMuljono If one of the answers posted worked for you, you can click the check mark below the vote buttons to mark it as accepted. – anonymoose May 07 '17 at 16:22
3

When you declare char string[]="Hello" you declare an array of characters.

string points to the first element of the array. * is known as the dereferencing operator.

Suppose ptr is an integer pointer. *ptr will give you the content of the memory location pointed by the pointer ptr. At the time of declaration you have to declare it as int *ptr so that the compiler knows that ptr is a pointer variable(hence the asterix there).


when you execute printf("first character is %c", *my_pointer); the function expects a character corresponding to %c. The declaration char *string and char string[] are roughly(not completely) equivalent. my_pointer is a character type pointer. *my_pointer dereferences my_pointer. In other words *my_pointer gives you the content of my_pointerie the first character in your string.


However a %s expects a string (a character array, which is basically a char pointer) as the corresponding argument in printf. *my_pointer is a character. my_pointer can be treated as a string. Also print will treat the argument as a string and print the who;e thing till \0.


my_pointer=array_of_words "assigns" the value of array_of_words to my_pointer.

array_of_words[] is an array, so the value of array_of_words is basically the memory address of the first element of the array(notice the absence of []). In effect my_pointer now points to the first element of the array.

Hope this explains it.

Parth K
  • 587
  • 5
  • 18
  • "`string` points to the first element of the array" --> Not quite. `string` is an array, not a pointer. In some contexts. `string` is converted to a pointer to its first element such as `char *my_pointer=string;`, yet `string` is still an array, the value assigned is a pointer. – chux - Reinstate Monica May 06 '17 at 19:26
  • Thank you for the explanation!!! Still confuse in some part!! *my_pointer=array_of_words copy the address of the first content of array_of_the_words which is 'o'? And char *my_pointer=array_of_the_words means we want *my_pointer has same address as array_of_the_words which refer to'o'(?) if my_pointer in printf("%s\n",my_pointer) refers to memory address of*my_pointer Then why not it produce 'one' and not produce 'o' ?? – fiksx May 06 '17 at 22:58
  • @chux can you please explain the difference – Parth K May 07 '17 at 01:42
  • @ParthK "`string` points to the first element of the array." lacks context. `string` is an _array_, not a pointer. – chux - Reinstate Monica May 07 '17 at 04:21
3

Lets assume string variable is located at memory address of 100. In C, a NUL character(\0) is automatically appended.

string 
|-------|
|hello\0|
|-------|
100

char *my_pointer = string;

Can be broken down to 2 statements:

 char *my_pointer;
 my_pointer = string;

Since my_pointer is a pointer to char, the value of my_pointer is an address which points to char.

 my_pointer
 |------|
 |100   |
 |------|

*my_pointer is an operation like addition or substraction. It means to go to that memory address and fetch the value. There is a fancy name for this: DEREFERENCING.

*my_pointer retrieves the first character at memory address of 100 which is h. Now why just h? Not the rest? That's because the printf() asked for a character with %c format specifier. If you want the whole string, you can do it with

  printf("%s\n", my_pointer );  

Note that, there is no dereference character. In this case, my_pointer becomes the memory address which is 100. Since there is %s format specifier, it will read from memory address 100 till a NUL byte character which is '\0'. This marks the end of the string.

Moving to 2nd example, array_of_words has 3 strings. The definition of a string is when characters ends with \0 (NUL character).

Lets say array_of_words is stored in memory address of 200.

 array_of_words
 |-----------------|
 |one\0two\0three\0|
 |-----------------|
 200



char *my_pointer=array_of_words;

 my_pointer
 |------|
 |200   |
 |------|

printf("%s \n",my_pointer);

returns characters starting from memory address of 200 till '\0' character.

This is why, one shows up only.

Hope I explained it correctly and hope it helps you to understand a little better.

Pointer is a very challenging subject. There are books written on just this topic.

Nguai al
  • 958
  • 5
  • 15
  • Thankyou for the detail explanation!!! Just want to clarify : *my_pointer in printf refer to what is at the memory address/value inside it? While my_pointer with no dereference character refer to memory address which is (*my_pointer=string) we want my_pointer has same memory address as variable array_of_words, inside the memory there is "one\0two\0three"? – fiksx May 06 '17 at 17:15
  • `*my_pointer in printf refer to what is at the memory address/value inside it?` YES. RIGHT ON. `While my_pointer with no dereference character refer to memory address which is (*my_pointer=string)` YES!!! GREAT!!! I was referred to this link. I find it very helpful. [link](http://www.c-faq.com) – Nguai al May 06 '17 at 18:50
  • *my_pointer=array_of_words copy the address of the first content of array_of_the_words which is 'o'? And char *my_pointer=array_of_the_words means we want *my_pointer has same address as array_of_the_words which refer to'o'(?) if my_pointer in printf("%s\n",my_pointer) refers to memory address of *my_pointer Then why not it produce 'one' and not produce 'o' ?? – fiksx May 06 '17 at 22:56
2

the printf function part in the first code using asterisk symbol means to point what is inside pointer (my_pointer) which is the address of variable string that refer to the pointer string for an array that point the memory address of the first word in array "hello". is my understanding true?

Ans: the *my_pointer in printf means the value represented by the memory address currently the pointer my_pointer is pointing at. i.e. 'h'. Pointer knows no array; it only knows a single memory address.

You see, the * during declaration and definition mean two different things. The former means the type of variable is a pointer to a char type value, and the later means the ValueOf operator(*)


when I change %c in printf("first character is %c", *my_pointer); to %s, the program crash. i want to know why i cant use %s

Ans: This happened because when printf sees a %s placeholder, it expects the supplied object to be a pointer so that it can iterate from the first char to the null value(\0). But in your case it found a char which is also considered as 8-bit integer, so the renderer starts loading chars starting from memory address 104 to till it finds \0. So when it is out of memory allocated, it crashes.

what is the different if i dont use asterisk in my_pointer in printf("first character is %c", my_pointer);

Ans: As I already said; char is also a 8-bit unsigned integer, so compiler thinks that you have supplied a char(because my_pointer returns the memory address which is integer if you remember) and tries to render it; but unfortunately there is no such printable char so you see a blank.


While in second code my_pointer variable didnt use asterisk(*) in {printf("%s \n",my_pointer);}. in this code is my_pointer refer to the address of array_of_words variable or what is inside of my_pointer?

Ans: my words earlier should answer this question

why the output is 'one' not 'o'?

Ans: you have \0s in the string and printf searches for \0 to know that the string has ended. So first time it finds null value; it terminates the rendering.

Shiva
  • 11,485
  • 2
  • 67
  • 84
  • Thankyou for detailed explanation! Need few clarification! The character expect the corresponding character of %c that refer to'h' while %s corresponding to first char until null value, and it expect to be a pointer not only single character 'h' so it crash? – fiksx May 06 '17 at 18:25
  • yes indeed. note that 'h' is treated as a 8bit integer I.e. 104 – Shiva May 06 '17 at 18:48
  • *my_pointer=array_of_words copies the address of first element of the content of array_of_the_words into my_pointer but why in printf (%s\n,my_pointer) produce 'one' not 'o'? Is it because my_pointer in printf refer to the memory address?? And for char *my_pointer is it possible to have value more than one character? For example "hello" inside the pointer(?) – fiksx May 07 '17 at 11:26