RGS
RGS

Reputation: 981

Different uses of pointers(*) in C

I am currently learning C with http://c.learncodethehardway.org/book/ and we are supposed to figure out some weird things on our own.

First of all I found this webpage that has already helped me understand some things about functions and function definitions and pointers and their use. Now the problem comes to when I see some "string" definitions.

Please correct me if these assumptions I am going to make are wrong:

char name[] = "John"; // creates an array of characters with these four letters + '\0'

A "string" is just an array of characters ending with '\0'.

I also read that a * before an identifier usually means that it is a pointer. For example:

int myNum = 18;
int *myNum_pointer = &myNum; // do I need the '&'?

If those assumptions are right, I don't understand what is going on here:

char *name = "John";

Is that a pointer to a string? Or is it another way of defining a string?? If so, is

char *name[] = "John";

the actual pointer to the "string"? (which is just an array of characters?).

EDIT Reading all your answers and comments I must ask another thing. "type char *" is a pointer to a char, right?

Upvotes: 2

Views: 190

Answers (6)

Nasser Al-Shawwa
Nasser Al-Shawwa

Reputation: 3653

Let's look at the line:

int myNum = 18;

In that line, you define a variable which has several properties:

  1. Identifier : the variable name myNum
  2. Type : int
  3. Address : this is it's location in memory. For the purpose of this explanation, I'm giving it a value of 0xa1, but it could be any value of the sort.
  4. Value: 18

In order to get a variable's address, you use the & operator. In this case, the line:

int *myNum_pointer = &myNum;

On the right hand side, &myNum returns the address of myNum, which in our case evaluates to 0xa1. And we are storing that in a variable called myNum_pointer, which has the type pointer-to-int, which means that it stores the address of an int variable. Because myNum_pointer is a variable in it's own right, it also has it's own properties:

  1. Identifier : the variable name myNum_pointer
  2. Type : int* (pointer-to-int)
  3. Address : it's own location in memory. let's say it's 0xa2.
  4. Value: 0xa1 (the address of myNum).

So, yes, you do need the & operator.

As for the part about the string: Don't define a string in C in this way.

char name[] = "John"; // Good
char *name  = "John"; // Bad

This is because although arrays and pointers are related, they are not the same thing. Some compilers will warn you that the second statement is deprecated in C.

And finally,

char *name[] = "John";

Is incorrect. Because here you are saying the name is an array of pointers to characters, when it's just an array of characters.

"John" is actually a string literal, which is an array of {'J', 'o', 'h', 'n', 0}, where 0 is the null-termination character which signifies the end of a string in C. In fact, without the last 0, {'J', 'o', 'h', 'n'} would simply be an array of characters, and not a proper string, which is another important distinction.

Upvotes: 1

Jayesh Bhoi
Jayesh Bhoi

Reputation: 25865

int myNum = 18;
int *myNum_pointer = &myNum; // do I need the '&'?

The type of myNum is int, which contains integer.

The type of myNum_pointer is int *, which contains address of integer variables.

-----------------------------------------------------
variables: | myNum         | myNum_pointer          |
-----------------------------------------------------
address  : | 0x12341234    | 0x12341238             |
-----------------------------------------------------

the & operator gets the address of operand. So, &myNum is equal to 0x12341234

So the variables are initialized like this:


variables: | myNum          | myNum_pointer  |
---------------------------------------------
address  : | 0x12341234     | 0x12341238     |
---------------------------------------------
value    : | 18              | 0x12341234    |
---------------------------------------------

Now

  char *name = "John";

defines name as a pointer to the first character in the string. The assignment means that as soon as the program loads, the pointer is set to hold the address of where the string is stored. It put string literal in read only part. pointers only hold an address, they cannot hold all the characters in a character array. This means that when we use a char * to keep track of a string, the character array containing the string must already exist.

EX>

char name[] = "John";
char *name2;
name2=name;

name @2000
----------------------
| j | o | h | n | \0 |
----------------------

name2 @3000
--------
| 2000 |
--------

Also

For pointer to string array you can define it like

char * mystr[10];

After that you can initilize it by like

mystr[i]="john";

OR at define time also you can initialize like

const char *digitnames[] = {"zero", "one", "two", "three",
        "four", "five", "six", "seven", "eight", "nine"};

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310930

This statement

char name[] = "John"; 

means that name is an array of characters that will contain the following sequence

{ 'J', 'o', 'h', 'n', '\0' }

In fact you could write

char name[] = { 'J', 'o', 'h', 'n', '\0' };

These records are equivalent.

As for this statement

char *name = "John";

then there are the following actions made by the compiler. It creates an array of type char[5] to store the string literal and then assigns the address of the first character of this array to pointer name. So name will contain the address of the first character of the string literal. Though string literals in C has types of non-const arrays you may not change them. So it would be better to write

const char *name = "John";

For this statement

char *name[] = "John";

the compiler shall issue an error becuase to initialize an array (except character arrays) there must be used a brace-init list. The valid record will look as

char *name[] = { "John" };

In this case the array would have only one element of type char * that would point to the first character of the string literal. The string literal itself would be placed in memory as an array of type char[5] by the compiler.

As for the difference between records

int myNum = 18;
int *myNum_pointer = &myNum; // do I need the '&'?

and

char *name = "John";

then in the first record there is a scalar object myNum, You have to apply operator & that to get its address. While in the second record the string literal is an array. In expressions such this it is adjasted by the compiler to a pointer to the first element of the array. So you have no apply operator & for the string literal. The expression in the right side has already type char *.

Upvotes: 4

Jonathan
Jonathan

Reputation: 1100

To answer your question of:

int myNum = 18;
int *myNum_pointer = &myNum; // do I need the '&'?

Yes, you need the & (which is the Address-of operator). This assigns the pointer myNum_pointer the address of myNum. If you take out the &, you are assigning the number in myNum directly to the pointer, which is a bad thing, and not what is intended. The problem would occur when you later use myNum_pointer, and it points to memory address 18 instead of the memory address of the myNum variable (if the compiler even accepts it). This would likely cause a segmentation fault at run time, which can be tricky to debug.

Upvotes: 0

user3733555
user3733555

Reputation:

I guess that this is a duplicate of hundreds of other qustions, but I'hm going to answer it anyway.

First, the '&' is a unary operator for the adress of a variable. So, for example, &foo could be an adress like 0xffff. So you definitely need the '&', because otherwise, if foo==1, your pointer would be on the adress 0x0001, and if you wanted to change the value, you would get a segfault (I guess it wouldn't even compile).

Second:

char* name="John";

does two things. It allocates an unchangable part in the memory and writes "John\0" into it. You have a pointer to that memory, but you can't change it, e.g write "john\0".

Third:

char* name[]

is a pointer to an array of chars. it can also be written like this:

char** name

or this:

char name[][]

It is actually an array of strings.

Fun fact: a '*' in front of a pointer gives back the value of the object the poiner points to. E.g:

int i=0;
int* pi;
pi=&i;
i==*pi  //this is true

Upvotes: 0

Fred Foo
Fred Foo

Reputation: 363517

char *name = "John";

defines an anonymous, statically allocated array of five bytes holding {'J', 'o', 'h', 'n', 0}, and declares a pointer name which initially points to the first element of the aforementioned array. That's the rule in C: an array "decays" into a pointer to its first element.

char *name[] = "John";

is invalid. It defines an array of char as before, but then tries to assign it to an array of char pointers, which makes no sense. The use case for char *[] is to store (pointers to the first char of) multiple strings:

char *names[] = {"John", "Mary"};

Read as: names is an array ([]), each element of which is a char*; this array we initialize with the elements "John" and "Mary", and since we're initializing pointers, these char arrays decay into pointers to their first elements.

Upvotes: 1

Related Questions