1

I have the following source :

/*file a2ptr.c */ 
#include <stdio.h>
#include <stddef.h>
typedef struct m_St m_St;
struct m_St
{
    size_t idx;
    size_t m_data[8];
}*x;

size_t GetSize(m_St *s)
{
    s->idx=1;
    return (sizeof((s->idx ? x : s)->m_data));
}
int main(void)
{
    m_St s = { 0 };
    printf("GetSize() returns: %zu\n", GetSize(&s));
    return 0;
}

On a 32-bit Linux using GCC 4.8.1, this code produces the following output :

$ gcc -Wall -Werror a2ptr.c  
$ ./a.out  
GetSize() returns: 32

My question :
Is (s->idx ? x : s)->m_data a valid expression in C ?
Why GetSize() returns the size of the whole array, (in bytes) and not the size of the pointer to its first element(e.g., sizeof(size_t)) ?

LihO
  • 41,190
  • 11
  • 99
  • 167
boleto
  • 1,149
  • 1
  • 22
  • 32
  • 3
    **`6.5.3.4 The sizeof operator, 1125:`** `When you apply the sizeof operator to an array type, the result is the total number of bytes in the array.` And `sizeof` is a compilation time operator. – Grijesh Chauhan Sep 23 '13 at 05:23
  • 1
    Common sense (or the one cent question): if it was, how would you determine the size of the array? It would be practically pointless. –  Sep 23 '13 at 05:28
  • From the [ISO C99 Standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf): **§6.5.3.4** The sizeof operator 88) When applied to a parameter declared to have array or function type, the sizeof operator yields the size of the adjusted (pointer) type. Does this quote applies to my example? Any point where did I miss? – boleto Sep 23 '13 at 05:35
  • @boleto The "parameter" word. That clause is for function arguments. An array automatically decays into a pointer when passed to a function, but not when it's the immediate argument of the `sizeof` operator. See my updated answer. –  Sep 23 '13 at 06:07
  • 1
    @boleto: A parameter defined with an array type `void func(int array[]);` is "adjusted" at compile time; it really is a pointer: `void func(int *array);`. That's why `sizeof array` yields the size of the pointer. The "decay", or implicit conversion, of an array expression to a pointer is a separate language rule. – Keith Thompson Sep 23 '13 at 06:29
  • You don't need any of that ternary expression nonsense. Just 'return sizeof m_St.m_data'. The array is converted to a pointer by being passed as a parameter, not by the sizeof operator. – user207421 Sep 23 '13 at 07:04

4 Answers4

3

Is (s->idx ? x : s)->m_data a valid expression in C ?

Yes.

Why GetSize() returns the size of the whole array, (in bytes) and not the size of the pointer to its first element(e.g., sizeof(size_t))?

Read:

6.5.3.4 The sizeof operator, 1125:

When you apply the sizeof operator to an array type, the result is the total number of bytes in the array.

According to this when sizeof is applied to the name of a static array identifier (not allocated through malloc), the result is the size in bytes of the whole array rather then just address. This is one of the few exceptions to the rule that the name of an array is converted/decay to a pointer to the first element of the array, and it is possible just because the actual array size is fixed and known at compile time, when sizeof operator evaluates. So 'array name' not converted into pointer.

To find length of array read: Weird behavior when printing array in C?

Read also:

1118
The sizeof operator shall not be applied to an expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an expression that designates a bit-field member.

1119
The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type.

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 1
    "And sizeof is a compilation time operator." - in this case, yes. Don't forget C99 VLAs, which require it to be a run-time operation. –  Sep 23 '13 at 05:32
  • @H2CO3 I don't know that, give link. Should I write in C **?** – Grijesh Chauhan Sep 23 '13 at 05:33
  • (Should write in C - what should you write in C? I don't understand.) It's in the same standard paper you are quoting :) –  Sep 23 '13 at 05:34
  • 6.5.3.4/2 If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant. – Yu Hao Sep 23 '13 at 05:38
  • @YuHao, H2co3: got `1122 If the type of the operand is a variable length array type, the operand is evaluated;` – Grijesh Chauhan Sep 23 '13 at 05:40
  • @H2CO3 And as I know C99 supports VLA so it runtime operator in C99. Am I correct **?** – Grijesh Chauhan Sep 23 '13 at 05:42
  • 2
    @GrijeshChauhan In C99, `sizeof` is still compile time operator when the operand isn't a VLA. – Yu Hao Sep 23 '13 at 05:45
  • @YuHao this is very interesting to know. clear to me now. Thanks! – Grijesh Chauhan Sep 23 '13 at 05:51
  • @Grijesh Chauhan I think that no conversion on non-lvalue array is done in my example, and sizeof operator computes the size of the whole array, but just wanted to be sure. – boleto Sep 23 '13 at 06:04
  • @boleto yes **no** conversion that is what it returns 32 but not sizeof pointer in your system. – Grijesh Chauhan Sep 23 '13 at 06:08
  • What specific document are the quotes in this answer from? I do not believe the text “When you apply the sizeof operator” appears in the 1999 or 2011 C standard. – Eric Postpischil Sep 23 '13 at 10:28
  • @EricPostpischil I quoted from [this: Link](http://c0x.coding-guidelines.com/6.5.3.4.html) I read they explained very nicely, I quoted it in my many answer I got good votes. One I quoted from [msdn](http://msdn.microsoft.com/en-us/library/0w557fh7%28v=vs.80%29.aspx). – Grijesh Chauhan Sep 23 '13 at 10:39
  • @GrijeshChauhan: Please do not give quotes that could be mistaken for quotes from the C standard without making it clear that they are not. – Eric Postpischil Sep 23 '13 at 10:53
  • "when sizeof is applied to the name of a static array identifier (not allocated through malloc)" Well, what you get from malloc is a pointer. You don't have an "array". So it's enough to just say "when sizeof is applied to an array". – newacct Sep 24 '13 at 06:36
  • @newacct yes, that is not pointer but some new students confuses that why I written like this. – Grijesh Chauhan Sep 24 '13 at 08:30
2

Array is converted to a pointer when sizeof expression is used?

No.


Now seeing your question in comments:

From the ISO C99 Standard: §6.5.3.4 The sizeof operator 88) When applied to a parameter declared to have array or function type, the sizeof operator yields the size of the adjusted (pointer) type. Does this quote applies to my example? Any point where did I miss?

You missed the word parameter. This is basically just another way to say that one can't really pass arrays to a function, only pointers, because arrays always decay into pointers when passed to a function. The clause you are citing concerns the following case:

void foo(char arr[1000])
{
    // will print sizeof(char *), because in a function argument context,
    // (and ONLY there), T array[N] is the same as T *arrray
    printf("%zu\n", sizeof(arr));
}

Now if your array is..., well, a real array, and not a disguised pointer, then it does not decay to a pointer if it is the argument of the sizeof operator.

0
size_t m_data[8];
return sizeof(m_data);   // <-- in this case same as return (sizeof(size_t) * 8);

so if you want to return the count of elements, you should do:

size_t m_data[8];
return ( sizeof(m_data) / sizeof(size_t) );

"Array is converted to a pointer when sizeof expression is used?" No. Your confusion is probably based on something, which is called array decaying, when an array is converted (decayed) into a pointer and the ability of retrieving the length of the array using sizeof is lost:

size_t getSize(size_t* myDecayedArray) {
    return sizeof(myDecayedArray);     // <-- same as return ( sizeof(size_t*) );
}
...
size_t m_data[8];
return getSize(m_data);                       // <-- array decayed into pointer

see What is array decaying?

Community
  • 1
  • 1
LihO
  • 41,190
  • 11
  • 99
  • 167
-1

sizeof is computed at compile time - not run time.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127