Madona wambua
Madona wambua

Reputation: 1428

Pointers and Arrays in C, Need for more Understanding

I was doing some pointers and arrays practice in C and I noticed all my four methods returned the same answer.My question is are there disadvantages of using any one of my below methods? I am stunned at how all these four give me the same output. I just noticed you can use a pointer as if it was an array and you can also use an array as if it was a pointer?

char *name = "Madonah";
int i= 0;
for (i=0;i<7; i++){
    printf("%c", *(name+i));
}

char name1 [7] = "Madonah";
printf("\n");
int j= 0;
for (j=0;j<7; j++){
    printf("%c", name1[j]);
}

char *name2 = "Madonah";
printf("\n");
int k= 0;
for (k=0;k<7; k++){
    printf("%c", name2[k]);
}

char name3 [7] = "Madonah";
printf("\n");
int m= 0;
for (m=0;m<7; m++){
    printf("%c", *(name+m));
}

Results:

Madonah
Madonah
Madonah
Madonah

Upvotes: 15

Views: 1354

Answers (9)

scarecrow
scarecrow

Reputation: 1

An array is just a variable that contains several values, each value has an index, you probably know that already.
Pointers are one of those things you dont need to know about until you realize you need to use them. Pointers are not variables themselves they are literally pointers to variables.
An example of how and why you might want to use a pointer.
You create a variable in one function which you want to use in another function.
You could pass your variable to the new function in the function header. This effectively COPIES the values from the original variable to a new variable local to the new function. Changes made to it in the new function only change the new variable in the new function.
But what if you wanted changes made in the new function to change the original variable where it is in the first function ?
You use a pointer.
Instead of passing the actual variable to the new function, you pass a pointer to the variable. Now changes made to the variable in the new function are reflected in the original variable in the first function.
This is why in your own example using the pointer to the array and using the actual array while in the same function has identical results. Both of them are saying "change this array".

Upvotes: 0

Giorgi Moniava
Giorgi Moniava

Reputation: 28685

Just in addition to what others said, I will add an image for better illustration. If you have

char a[] = "hello";
char *p = "world";

What happens in first case enough memory is allocated for a (6 characters) on the stack usually, and the string "hello" is copied to memory which starts at a. Hence, you can modify this memory region.

In the second case "world" is allocated somewhere else(usually in read only region), and a pointer to that memory is returned which is simply stored in p. You can't modify the string literal in this case via p.

Here is how it looks:

enter image description here

But for your question stick to notation which is easier, I prefer []. More info on relationship between arrays and pointers is here.

Upvotes: 6

haccks
haccks

Reputation: 106122

It is true that pointers and arrays are equivalent in some context, "equivalent" means neither that they are identical nor even interchangeable. Arrays are not pointers.
It is pointer arithmetic and array indexing that are equivalent, pointers and arrays are different.

which one is preferable and the advantages/Disadvantages?

It depends how you want to use them. If you do not wanna modify string then you can use

char *name = "Madonah";  

It is basically equivalent to

char const *name = "Madonah";  

*(name + i) and name[i] both are same. I prefer name[i] over *(name + i) as it is neat and used most frequently by C and C++ programmers.

If you like to modify the string then you can go with

char name1[] = "Madonah";

Upvotes: 23

alk
alk

Reputation: 70981

can I know which one is easy to use [...]

Try sticking to use the indexing operator [].

One time your code gets more complex and you then notice that things are "more easy" to code using pointer arithmetical expressions.

This typically will be the case when you also start to use the address-of operator: &.

If for example you see your self in the need to code:

char s[] = "Modonah";
char * p = &s[2]; /* This gives you the address of the 'd'. */

you will soon notice that it's "easier" to write:

char * p = s + 2; /* This is the same as char * p = &s[2];. */

Upvotes: 1

barak manos
barak manos

Reputation: 30156

  1. char name[] = "Madonah";
  2. char* name = "Madonah";

When declared inside a function, the first option yields additional operations every time the function is called. This is because the contents of the string are copied from the RO data section into the stack every time the function is called.

In the second option, the compiler simply sets the variable to point to the address of that string in memory, which is constant throughout the execution of the program.

So unless you're planning to change the contents of the local array (not the original string - that one is read-only), you may opt for the second option.

Please note that all the details above are compiler-implementation dependent, and not dictated by the C-language standard.

Upvotes: 1

technosaurus
technosaurus

Reputation: 7812

it is convenient to use array syntax for random access

int getvalue(int *a, size_t x){return a[x];}

and pointer arithmetic syntax for sequential access

void copy_string(char *dest, const char *src){while((*dest++=*src++));}

Many compilers can optimize sequential accesses to pointers better than using array indices.

Upvotes: 2

Targeloid
Targeloid

Reputation: 227

For practicing pointer and array idioms in C, those are all valid code blocks and illustrative of the different ways of expressing the same thing.

For production code, you wouldn't use any of those; you would use something both easier for humans to read and more likely to be optimized by the compiler. You'd dispense with the loop entirely and just say:

printf("%s", name);

(Note that this requires name include the \0 character at the end of the string, upon which printf relies. Your name1 and name3 definitions, as written, do not allocate the necessary 8 bytes.)

If you were trying to do something tricky in your code that required one of the more verbose methods you posted, which method you chose would depend on exactly what tricky thing you were trying to do (which you would of course explain in code comments -- otherwise, you would look at your own code six months later and ask yourself, "What the heck was I doing here??"). In general, for plucking characters out of a string, name[i] is a more common idiom than *(name+i).

Upvotes: 1

P.P
P.P

Reputation: 121427

In C, a[b], b[a], *(a+b) are equivalent and there's no difference between these 3. So you only have 2 cases:

char *name = "Madonah"; /* case 1 */

and

char name3 [7] = "Madonah"; /* case 2 */

The former is a pointer which points to a string literal. The latter is an array of 7 characters.

which one is preferred depends on your usage of name3.

If you don't intend to modify then the string then you can use (1) and I would also make it const char* to make it clear and ensure the string literal is not modified accidentally. Modifying string literal is undefined behaviour in C

If you do need to modify it then (2) should be used as it's an array of characters that you can modify. One thing to note is that in case (2), you have explicitly specified the size of the array as 7. That means the character array name3 doesn't have a null terminator (\0) at the end. So it can't be used as a string. I would rather not specify the size of the array and let the compiler calculate it:

char name3 [] = "Madonah"; /* case 2 */
/* an array of 8 characters */

Upvotes: 11

Richard Pennington
Richard Pennington

Reputation: 19985

In all cases, in C pointer + index is the same as pointer[index]. Also, in C an array name used in an expression is treated as a pointer to the first element of the array. Things get a little more mystifying when you consider that addition is commutative, which makes index + pointer and index[pointer] legal also. Compilers will usually generate similar code no matter how you write it.

This allows cool things like "hello"[2] == 'l' and 2["hello"] == 'l'.

Upvotes: 2

Related Questions