-7
#include<stdio.h>

int strlen1(char *s){

    char *p=s;
    printf("%s\n",s);

    printf("size of s=%d\n",sizeof(s));

    while(*p!='\0')

    p++;

    return p-s;

}

int main(){

    int len;
    char c[]="welcome back ";
    len=strlen1(c);
    printf("%d",len);
    return 0;

}

In this code the char array passed as parameter of function strlen() in which s is a pointer(address of first element of array c) then why it prints the whole array and its size is only 8.And also assigning char pointer p as s will not reference its address rather its value.Please clear my concepts and basics of this whole code. Thanks in advance.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
anshika24
  • 1
  • 2
  • 2
    In C a "string" is an array of `char`s, with at least one element being equal to `0`. – alk Aug 10 '16 at 15:48
  • It prints the size 8 because that is the size of a `char *` pointer value on your system. Also, the format specifier `%d` expects an argument of type `int`, but your argument `sizeof(s)` has type `size_t`. You can fix that by casting the argument to the expected type: `(int)sizeof(s)`. – Ian Abbott Aug 10 '16 at 16:51
  • Possible duplicate of [Sizeof an array in the C programming language](http://stackoverflow.com/questions/1975128/sizeof-an-array-in-the-c-programming-language) – Mark Plotnick Aug 10 '16 at 18:00

3 Answers3

2

assigning char pointer p as s will not reference its address rather its value

When you assign s to p you are actually assigning the address.
If you wanted to assign just the value, then you would need to do something like this:

char p; //create a char called p
p = *s; //value at p = value at s

But then you can't scan through the array in your while loop using p.


why it prints the whole array

%s means keep printing until you see a null character. So because p points to the first address of your string it prints the whole thing.


its size is only 8

sizeof(s) means what is the size of the variable s. You defined s as a char pointer, so it returns the size or a char pointer (8). The function you want is:

strlen(s);  

EDIT: Fixed the first example to remove undefined behavior.

Riley
  • 698
  • 6
  • 11
  • `strlen()` gives you the length of the string, which (hopefully ;-)) is different from the size of the array it might be held by. – alk Aug 10 '16 at 16:01
  • 2
    `char* p; *p = ...` this invokes undefined behaviour, as `p` is pointing "no where" and is being de-referenced. – alk Aug 10 '16 at 16:03
0

%s takes a memory address and prints the characters till it finds a null character.

When u initiallize a pointer at the time of declaration as in this case "char *p = s;" , the address of s is assigned to p and not the value.

  1. char *p; p=s;

  2. char *p=s;

Both are same things.

0

Under most circumstances, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

The exceptions to this rule are:

  • when the array expression is the operand of the sizeof or unary & operators;
  • when the array expression is a string literal used to initialize another array in a declaration (thus, the "welcome back " string literal used to initialize c is not converted to a pointer expression; instead, the contents of the string literal are copied to c).

When you call

len=strlen1(c);

the expression c is converted from type "14-element array of char" to "pointer to char", and this pointer expression is what actually gets passed to strlen1.

In the context of a function parameter declaration, T a[N] and T a[] are treated the same as T *a; a is declared as a pointer to T, not an array of T. This makes sense, since a function cannot receive an array expression as a parameter; it will have been converted to a pointer before being passed to the function.

then why it prints the whole array

That's how the %s conversion specifier works; it tells printf to start printing the sequence of characters beginning at the address specified by s until it sees a 0-valued byte.

its size is only 8

The type of the expression s is char *, so sizeof s is equivalent to sizeof (char *) (that is, the size of a pointer to char), so what you're displaying is the number of bytes required to store a pointer value, not the size of the string that s is pointing to.

Here's a memory map of how things play out on my platform, which may help understand some of these concepts:

           Item        Address   00   01   02   03
           ----        -------   --   --   --   --
"welcome back "       0x400c89   77   65   6c   63    welc
                      0x400c8d   6f   6d   65   20    ome.
                      0x400c91   62   61   63   6b    back
                      0x400c95   20   00   25   64    ..%d

              c 0x7fffa9c401a0   77   65   6c   63    welc
                0x7fffa9c401a4   6f   6d   65   20    ome.
                0x7fffa9c401a8   62   61   63   6b    back
                0x7fffa9c401ac   20   00   00   00    ....

            len 0x7fffa9c401bc   00   00   00   00    ....

              s 0x7fffa9c400e8   a0   01   c4   a9    ....
                0x7fffa9c400ec   ff   7f   00   00    ....

              p 0x7fffa9c40128   a0   01   c4   a9    ....
                0x7fffa9c4012c   ff   7f   00   00    ....

This is the state of things at the entry to strlen1.

The string literal "welcome back " is stored starting at address 0x400c89. The character array c is stored starting at address 0x7fffa9c401a0. The pointer object s is stored starting at address 0x7fffa9c400e8 and contains the address of the array object c (x86 is little-endian, so it reads from least-signficant byte to most-significant byte). The object s is only 8 bytes wide, which is why you got 8 as output for sizeof(s).

You should not use the %d format specifier to print a value of type size_t (which is what sizeof returns). If you're using C99 or later, use %zu; if you're using C89, use %lu and cast the value to unsigned long:

printf( "size of s=%zu\n", sizeof s ); // C99 or later
printf( "size of s=%lu\n", (unsigned long) sizeof s ); /* C89 */
John Bode
  • 119,563
  • 19
  • 122
  • 198