2
main()
{
char a[] = "Visual C++";
char *b = "Visual C++";
printf("\n %d %d",sizeof(a),sizeof(b));
printf("\n %d %d",sizeof(*a),sizeof(*b));
}

sizeof(a) gives me output: 11 ( that is length of the string)

Why is it so ?
Why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value and hence an integer?

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
Shivaji_Vidhale
  • 393
  • 1
  • 5
  • 14
  • 5
    Read: [What does sizeof(&arr) return?](http://stackoverflow.com/questions/15177420/what-does-sizeofarr-return/15177499#15177499) given a answer with diagrams and working codes – Grijesh Chauhan Jul 17 '13 at 16:10
  • 15
    And, just to be picky, `sizeof` is an operator, not a function. – Crowman Jul 17 '13 at 16:15
  • 1
    @shivaji_vidhale: "why is it so, why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value and hence an integer." A dollar says if you print it by using `puts(a)`, it doesn't "give you an address value". – Crowman Jul 17 '13 at 16:17
  • 1
    Also, `%d` is not the correct format specifier for `size_t` (the type what `sizeof` yields). What you are looking for is `%zu`. –  Jul 17 '13 at 16:19
  • I dont want to print a. Just want to know why doesn't sizeof(a) give the size of an integer. Since when I try to print a i get an address. – Shivaji_Vidhale Jul 17 '13 at 16:19
  • @Shivaji_Vidhale Because `a` is not an integer, in first place? –  Jul 17 '13 at 16:20
  • 2
    @Shivaji_Vidhale: "Since when I try to print a i get an address." One more time, you only get an address when you tell it to print an address. Just don't tell it to do that, and your confusion will go away. – Crowman Jul 17 '13 at 16:22
  • Consider this : `char a[10];` what do you think `sizeof(a)` evaluates to .... its `10*size of the a[0]` in this case ( I mean the array not allocated through malloc) its an exception to the normal result of `sizeof`. In case of arrays the array names decay to pointer. – 0decimal0 Jul 17 '13 at 16:29
  • 1
    @PHIfounder What do you mean by "it's an exception"? What would be the "normal result"? –  Jul 17 '13 at 16:31
  • @H2CO3 Exception means using the array names in `sizeof`.... normally it would result in the size of the datatype e.g, `char` `int` or pointers – 0decimal0 Jul 17 '13 at 16:35
  • 2
    @PHIfounder I don't think so. `sizeof()` always yields the size of its argument. There's no exception. –  Jul 17 '13 at 16:37
  • 1
    @H2CO3 In case of arrays it yields the size of the whole array .That's an exception . Normally it yields the size of the datatype whatever it may be . – 0decimal0 Jul 17 '13 at 16:40
  • 1
    @PHIfounder: "normally it would result in the size of the datatype" - the size of the datatype `char[11]` *is* 11, this is not an exception. – Crowman Jul 17 '13 at 16:41
  • 1
    @PHIfounder I still don't see why it is an exception. If an array is passed to `sizeof()`, it yields the size of the array. If any other object of type `T` is passed to it, then it gives back the size of `T`. –  Jul 17 '13 at 16:41
  • 1
    @H2CO3 OK I was writing it wrong ,I meant that the array name decays to pointer to the first element of the array that is `a[0]` but here sizeof yields the whole array size . What Paul griffiths says is right but I didn't mean that . – 0decimal0 Jul 17 '13 at 16:45
  • 1
    It only decays, or implicitly converts, when there is something it needs to convert to. `puts()`, for instance, is explicitly defined as taking an argument of type `const char *`, so the array implicitly decays to one. `char * b = a;` is even more explicit. But the `sizeof` operator will accept the plain array, so no implicit conversion needs to, or does, happen. It's not that `sizeof` makes an exception, rather that it does not provide any conditions in which an implicit conversion needs to take place, just like if you defined a function `void myfunc(char a[11]) {};`. – Crowman Jul 17 '13 at 16:47
  • 3
    @PaulGriffiths: That is not an accurate description of the semantics. There is an explicit exception for `sizeof`. C 2011 6.3.2.1 3: “Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.” – Eric Postpischil Jul 17 '13 at 16:57
  • @EricPostpischil: +1 for quoting from the standard, and fair play. I'd still say that matches "`sizeof` ... does not provide any conditions in which an implicit conversion needs to take place", although I stand corrected that it can implicitly convert in the absence of something that requires it. – Crowman Jul 17 '13 at 17:02
  • 1
    And, for @PHIfounder's benefit, the "exception" is to the general rule that expressions of type "array of type" convert to expressions of type "pointer to type", not an exception to how the `sizeof` operator functions. `sizeof` does get an expression of type "array of type", it doesn't get an expression of type "pointer to type" and then makes an exception to treat it differently from other expressions. – Crowman Jul 17 '13 at 17:10
  • @Shivaji_Vidhale You can start with Pointers in C by Yashwant Kanetkar. – nj-ath Jul 18 '13 at 07:44

4 Answers4

10

Whenever you refer to the name of the array in your program, It normally decays to a pointer to the first element of the array. One of the exception to this rule is the sizeof operator. So when you consider the following code.

int main()
{
   char a[] = "Visual C++";
   printf("sizeof(a)=%d\n",sizeof(a)); /* Here sizeof(a) indicates sizeof array */
   printf("a=%p",a); /* Here the array name, passed as an argument to printf decays into a pointer of type (char *) */
   return 0;
}
Vivek Maran
  • 2,623
  • 5
  • 38
  • 52
  • I'm not sure of the accuracy (or the English semantics) of "a refers to the pointer", but it is certainly true that a pointer to the first element of `a` is passed as the second argument to `printf`. – William Pursell Jul 17 '13 at 16:31
  • 3
    To expand on that: the correct terminology to use would be "the array decays into a pointer" or it is "implicitly converted to a pointer". –  Jul 17 '13 at 16:32
  • Thanks for the suggestion.Improved the comment. – Vivek Maran Jul 17 '13 at 16:37
  • Yes type of `a` is `char[N]` and type of pointer is `char*` (type of `b`), but in most operations `char[N]` decays into `char*` but not with `sizeof()`. – Grijesh Chauhan Jul 17 '13 at 16:57
3

In the declaration char a[] = "Visual C++", a is an array of 11 char. So its size is 11 bytes.

In the declaration char *b = "Visual C++", b is a pointer to char. So its size is four bytes (in the C implementation you are using).

In the expression printf("%s", a), a is also an array. However, it is automatically converted to a pointer to the first element of the array. So a pointer to char is passed to printf.

This conversion happens automatically unless an array is the argument of &, sizeof, or _Alignof or is a string literal used to initialize an array of char. Because it happens automatically, people tend to think of array names as pointers. However, they are not.

Incidentally, sizeof is an operator, not a function.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
1

When sizeof is applied to the name of a static array (not an array allocated through malloc), the result is the size in bytes of the whole array. This is one of the few exceptions to the rule that the name of an array is converted to a pointer to the first element of the array, and is possible just because the actual array size is fixed and known at compile time, when sizeof operator is evaluated.

AnthonyLambert
  • 8,768
  • 4
  • 37
  • 72
0

There are lots of errors, here.

"sizeof(a) gives me output: 11 (length of the string)"

The length of the string is 10, not 11. sizeof(a) gives you the length of the array.

"why is it so, why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value"

Here are two methods of "printing a" which do not "give you an address value":

puts(a);

and:

printf("%s\n", a);

so your logic is flawed, and this is the source of your confusion. "Printing a" only "gives you an address value" when you explicitly or implicitly elect to do so.

sizeof(a) gives 11 in this case because the C language defines the sizeof operator to give you the size of an array when an array is the operand. This, I'd argue, is the most natural behavior people would expect, so presumably that's why it is defined as such.

"and hence an integer."

In any case, an address is an address, not an integer. At best you could argue that it ought to give you the size of a pointer, but certainly not the size of an integer.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Crowman
  • 25,242
  • 5
  • 48
  • 56
  • 1
    "But hey, the size of an integer is 4 bytes, and the size of a pointer is 4 bytes too, and anyways, pointers are just integers!" (Better make this comment before OP does so.) –  Jul 17 '13 at 16:40