Yudop
Yudop

Reputation: 153

C: Behaviour of arrays when assigned to pointers

#include <stdio.h>

main()
{
  char * ptr;

  ptr = "hello";


  printf("%p %s" ,"hello",ptr );

  getchar();

}

Hi, I am trying to understand clearly how can arrays get assign in to pointers. I notice when you assign an array of chars to a pointer of chars ptr="hello"; the array decays to the pointer, but in this case I am assigning a char of arrays that are not inside a variable and not a variable containing them ", does this way of assignment take a memory address specially for "Hello" (what obviously is happening) , and is it possible to modify the value of each element in "Hello" wich are contained in the memory address where this array is stored. As a comparison, is it fine for me to assign a pointer with an array for example of ints something as vague as thisint_ptr = 5,3,4,3; and the values 5,3,4,3 get located in a memory address as "Hello" did. And if not why is it possible only with strings? Thanks in advanced.

Upvotes: 0

Views: 207

Answers (4)

Keith Thompson
Keith Thompson

Reputation: 263307

The first thing you should do is read section 6 of the comp.lang.c FAQ.

The string literal "hello" is an expression of type char[6] (5 characters for "hello" plus one for the terminating '\0'). It refers to an anonymous array object with static storage duration, initialized at program startup to contain those 6 character values.

In most contexts, an expression of array type is implicitly converted a pointer to the first element of the array; the exceptions are:

  • When it's the argument of sizeof (sizeof "hello" yields 6, not the size of a pointer);
  • When it's the argument of _Alignof (a new feature in C11);
  • When it's the argument of unary & (&arr yields the address of the entire array, not of its first element; same memory location, different type); and
  • When it's a string literal in an initializer used to initialize an array object (char s[6] = "hello"; copies the whole array, not just a pointer).

None of these exceptions apply to your code:

char *ptr;
ptr = "hello";

So the expression "hello" is converted to ("decays" to) a pointer to the first element ('h') of that anonymous array object I mentioned above.

So *ptr == 'h', and you can advance ptr through memory to access the other characters: 'e', 'l', 'l', 'o', and '\0'. This is what printf() does when you give it a "%s" format.

That anonymous array object, associated with the string literal, is read-only, but not const. What that means is that any attempt to modify that array, or any of its elements, has undefined behavior (because the standard explicitly says so) -- but the compiler won't necessarily warn you about it. (C++ makes string literals const; doing the same thing in C would have broken existing code that was written before const was added to the language.) So no, you can't modify the elements of "hello" -- or at least you shouldn't try. And to make the compiler warn you if you try, you should declare the pointer as const:

const char *ptr; /* pointer to const char, not const pointer to char */
ptr = "hello";

(gcc has an option, -Wwrite-strings, that causes it to treat string literals as const. This will cause it to warn about some C code that's legal as far as the standard is concerned, but such code should probably be modified to use const.)

Upvotes: 1

AnT stands with Russia
AnT stands with Russia

Reputation: 320531

"hello" is a string literal. It is a nameless non-modifiable object of type char [6]. It is an array, and it behaves the same way any other array does. The fact that it is nameless does not really change anything. You can use it with [] operator for example, as in "hello"[3] and so on. Just like any other array, it can and will decay to pointer in most contexts.

You cannot modify the contents of a string literal because it is non-modifiable by definition. It can be physically stored in read-only memory. It can overlap other string literals, if they contain common sub-sequences of characters.

Similar functionality exists for other array types through compound literal syntax

int *p = (int []) { 1, 2, 3, 4, 5 };

In this case the right-hand side is a nameless object of type int [5], which decays to int * pointer. Compound literals are modifiable though, meaning that you can do p[3] = 8 and thus replace 4 with 8.

You can also use compound literal syntax with char arrays and do

char *p = (char []) { "hello" };

In this case the right-hand side is a modifiable nameless object of type char [6].

Upvotes: 3

nagaradderKantesh
nagaradderKantesh

Reputation: 1690

#include <stdio.h>

main()
{
   char * ptr;

   ptr = "hello"; 

  //instead of above tow lines you can write char *ptr = "hello" 

   printf("%p %s" ,"hello",ptr );

   getchar();

}

Here you have assigned string literal "hello" to ptr it means string literal is stored in read only memory so you can't modify it. If you declare char ptr[] = "hello";, then you can modify the array.

Upvotes: 0

Jonathan Wood
Jonathan Wood

Reputation: 67223

Say what?

Your code allocates 6 bytes of memory and initializes it with the values 'h', 'e', 'l', 'l', 'o', and '\0'.

It then allocates a pointer (number of bytes for the pointer depends on implementation) and sets the pointer's value to the start of the 5 bytes mentioned previously.

You can modify the values of an array using syntax such as ptr[1] = 'a'.

Syntactically, strings are a special case. Since C doesn't have a specific string type to speak of, it does offer some shortcuts to declaring them and such. But you can easily create the same type of structure as you did for a string using int, even if the syntax must be a bit different.

Upvotes: -2

Related Questions