14

I am reading the chapter on arrays and pointers in Kernighan and Richie's The C Programming Language.

They give the example:

/* strlen:  return length of string s */
int strlen(char *s)
{
    int n;

    for (n = 0; *s != '\0'; s++)
        n++;
    return n;
}

And then say:

“Since s is a pointer, incrementing it is perfectly legal; s++ has no effect on the character string in the function that called strlen, but merely increments strlen’s private copy of the pointer. That means that calls like

strlen("hello, world");  /* string constant */
strlen(array);           /* char array[100]; */
strlen(ptr);             /* char *ptr; */

all work.”

I feel like I understand all of this except the first call example: Why, or how, is the string literal "hello, world" treated as a char *s? How is this a pointer? Does the function assign this string literal as the value of its local variable *s and then use s as the array name/pointer?

4
  • Some very good questions/answers on SO about strings, arrays, pointers, and their relationships. Just one example. And congrats on actually doing at least some research on the subject, which is a far-cry more than almost anyone else does before posting questions about this subject. Well written question. Commented Jan 21, 2013 at 19:28
  • Also note that K&R lacks plenty when it comes to good programming practice. When passing a string to a function that doesn't modify it, you should declare the parameter as const char* s. This is particularly important when a string literal is passed. Had your function attempted a write to *s you would invoke undefined behavior and the program could crash. Commented Jan 21, 2013 at 19:55
  • 1
    Thanks everyone for making this into such a great thread! It will be difficult/impossible to pick an accepted answer. With your answers, I went back and read the part of the book that precedes this example. I think the key sentence that I didn't notice before was By definition, the value of a variable of expression of type array is the address of element zero of the array. So, when I use a string literal as a parameter in a function, I am not passing the string literal itself but the "type array", which is a pointer to the 0th index in the string literal, which is an array. Commented Jan 21, 2013 at 20:07
  • 1
    Thank you Lundin! I actually came across that when trying to answer this question myself before posting here. More about what you mention (using const char *s rather than char *s) can be found at securecoding.cert.org/confluence/display/seccode/… Commented Jan 21, 2013 at 20:12

6 Answers 6

16

To understand how a string like "Hello World" is converted to a pointer, it is important to understand that, the string is actually hexadecimal data starting at an address and moving along till it finds a NULL

So that means, every string constant such as "Hello World" is stored in the memory somewhere

Possibility would be:

0x10203040 : 0x48 [H]
0x10203041 : 0x65 [e]
0x10203042 : 0x6C [l]
0x10203043 : 0x6C [l]
0x10203044 : 0x6F [o]
0x10203045 : 0x20 [' ']
0x10203046 : 0x57 [W]
0x10203047 : 0x6F [o]
0x10203048 : 0x72 [r]
0x10203049 : 0x6C [l]
0x1020304A : 0x64 [d]
0x1020304B : 0x00 [\0]

So, when this function is called with the above values in the memory, [left side is address followed by ':' and the right side is ascii value of the character]

int strlen(const char *s)
{
    int n;

    for (n = 0; *s != ′\0′; s++)
        n++;
    return n;
}

strlen("Hello World");

at that time, what gets passed to strlen is the value 0x10203040 which is the address of the first element of the character array.

Notice, the address is passed by value.. hence, strlen has its own copy of the address of "Hello World". starting from n = 0, following uptil I find \0 in the memory, I increment n and also the address in s(which then gets incremented to 0x10203041) and so on, until it finds \0 at the address 0x1020304B and returns the string length.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks Aniket. Does changing the parameter signature to const char *s restrain this function, or any function with such a signature, from manipulating the pointer variable locally? Does the const essentially turn this pointer into an array? K&R point out that "one difference between an array name and a pointer must be kept in mind. A point is a variable, so pa=a and pa++ [where pa is a pointer] are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal [where a is an array name]."
no, const only helps you to guard against accidentally modifying the contents of the array @dimadima. Arrays are internally treated as pointers, but pointers are not internally treated as arrays. An array name is a label to the start of an array. A subscript operator [i] dereferences the ith value in the array from the start of the array.
****prints and puts on wall****
What do you mean by stored somewhere? is it stored in the stack or the code segment?
3

"hello, world"

is an array of char (type is char[13]). The value of an array of char in an expression is a pointer to char. The pointer points to the first element of the array (i.e., the value of "hello, world" is &"hello, world"[0]).

Comments

1

Note that:

  • A pointer is (basically) a value pointing to a memory address.
  • A static string like "hello, word" is stored somewhere in memory

So, a pointer could as easily simply point to a static string as to any other (dynamical) structure that is stored in memory (like an array of characters). There is really no difference with the other provided examples.

Comments

1

Does the function assign this string literal as the value of its local variable *s and then use s as the array name/pointer?

Yes

1 Comment

"Yes", in the sense that the string literal is an array. Since by definition, the value of a variable of expression of type array is the address of element zero of the array, the value of the array is the address of its first element. This first address is assigned to s as a local function variable.
1

As it says in the first paragraph of the same page (Page 99, K&R2):

"By definition, the value of a variable or expression of type array is the address of element zero of the array."

The value of "hello, world" would be the address of 'h'.

1 Comment

Or in other words: Literal strings in C are bytes delimited with '\0' and found via their address. So When you pass "abc" to a function ,you are actually passing the address (a char * pointer) to the function as parameter. Also string literals should be treated read-only in C.
0
char str[] = "Hello, world";
strlen(str);

string in C are array of characters with terminating NULL ('\0'), that mean it should be in the memory some where.

so what is the difference of sending a stored string as above and sending it directly as below

strlen("Hello, World");

The answer is both are same, but where the string is stored and how it's handled, here comes the compiler and stack.

The compiler at compile time pushes the string in to stack and send the starting address (char*) in the stack, the calling function sees a pointer and access the string.

The compiler also add codes after exist form the function to restore the stack in the correct place thus deleting the temporary string created enter image description here Note: the above is implementation dependent of the compiler, but most of the compiler works this way

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.