2

There is something I can't understand in c. The following code:

#include <stdio.h>

int main(char* args){
    char abc[100];
    printf("%d %d", sizeof(abc), sizeof(abc+1));
}

outputs

100 4

I tought it should generate 100 100-1, which is:

100 99

Same for int abc[100]. It outputs

400 4

instead of

400 396

edit: Ok, so I saw your commands. abc+1 in an expression. therfore, the result is int, sizeof(int) == 4. So my other question is WHY in the first time I send a pointer for array and the result is the length of the array? The following:

int main(char* args){
    char abc[100];
    char *test;
    test = (char*)abc+1;
    printf("%d %d", sizeof(abc), sizeof(test));
}

Outputs 100 4

Weiner Nir
  • 1,435
  • 1
  • 15
  • 19
  • The syntax says: `sizeof expr`. Here `(abc-1)` is an expression. Remove the parentheses : `sizeof abc -1` and you'll get 396 or 99 . (this is because sizeof has a stronger precedence than '-' ) – wildplasser Dec 07 '13 at 18:25

4 Answers4

10

The expression

abc+1 

is a pointer. Your pointers would therefore appear to be 4 bytes wide.

On the other hand, the expression

abc

is an array of char of length 100 and so its size is 100.

And as for the version using int instead of char, I'm sure you can now apply the above reasoning to explain the output.


I think your edit to the question essentially asks:

Why is abc+1 a pointer, and abc an array.

The standard says:

Other operands - Lvalues, arrays, and function designators (ISO/IEC 9899:201x 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. If the array object has register storage class, the behavior is undefined.

So, when you write sizeof(abc) then abc does not meet the criteria required to convert the expression abc into a pointer. So abc is treated as an array. But in the expression sizeof(abc+1), abc+1 does not meet any of the listed exceptions and so is converted into a pointer.

Colloquially this is known as an array decaying to a pointer.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
6

abc+1 is a pointer; thus its size is the size of a pointer or address, and that is 4 on your system.

Notice that the size of a pointer is platform dependent. As one comment warns: "On Windows 64, a pointer is bigger than the size of a long."

You also ask why it gives you 100 first, if it gives you 4 after.

An array is like pointer but is not a pointer. When you first wrote sizeof(abc), it is not the size of a pointer that is compiled, but the size of your array. That's why it gives you 100 in the first try.

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
  • You are right it is plateform dependent. Though it is generally the case. – Stephane Rolland Dec 07 '13 at 18:28
  • 1
    Isn't size of integer taken as 16 bits in C [from wiki](http://en.wikipedia.org/wiki/C_data_types)? – hrv Dec 07 '13 at 18:28
  • @hrv http://stackoverflow.com/questions/11438794/size-of-c-int-is-2-bytes-or-4-bytes – Stephane Rolland Dec 07 '13 at 18:29
  • 1
    The size of a pointer is not the same as the size of an `int` except on a 32-bit platform. On 16-bit and 64-bit platforms, that is not true. On Windows 64, a pointer is bigger than the size of a `long`. The `i.e.` should be at most an `e.g.`. If you need an integer type that is big enough to hold a pointer, you need `uintptr_t` (or `intptr_t`) defined in ``. – Jonathan Leffler Dec 07 '13 at 18:32
  • @hrv nowhere in that wiki page does it state an int is 16 bits. C says an int needs to be _at least_ 16 bit though. – nos Dec 07 '13 at 18:33
  • 1
    This is pretty sloppy. Pointer size varies with platform. No general relationships apply here. On Windows, `sizeof(void*) != sizeof(long)` for 64 bit systems. – David Heffernan Dec 07 '13 at 18:33
  • 2
    @StephaneRolland, to avoid this pointer size fight, your answer can be something like `abc+1 is a pointer, thus its size is the size of an pointer adress (which apperars to be 4 bytes on your system).` – Atle Dec 07 '13 at 18:35
  • Yes, only you are comparing `sizeof(void*)` with `sizeof(long)`. There's simply no reason to make such a comparison. The size of a pointer is, well, the size of a pointer. – David Heffernan Dec 07 '13 at 18:36
  • @Nirock I have added a complement of information concerning your second question – Stephane Rolland Dec 07 '13 at 18:49
1

This is perfectly fine.

Since array's name is read only pointer which refer to first element's address in array. Whenever a feasible arithmetic operator (++,--,+,-) or the return is applied on array, It is treated as pointer.

sizeof is a operator which returns the block size (in bytes) holds by a type or a variable or a literal

when you used sizeof(array)
It returned 100.
since block size of array is 100.
you had not applied any arithmetic so array was treated as an array.

when you used sizeof(array+1)
It returned 4 (size of pointer in your machine).
It's treated as pointer as arithmetic operation was applied and pointer's block size is equivalent to long size (may vary).

The Mighty Programmer
  • 1,242
  • 12
  • 23
  • One more question, How does `char abc[10]` looks in the memory? like the following: `\0 \0 \0 \0 \0 \0 \0 \0 \0 \0`? – Weiner Nir Dec 07 '13 at 18:45
  • 1
    if **char abc[10]** is global variable(defined outsize of any function) then it is block whose cells contain **nul(/0)** or can say collections of 10 **/0 (nul)** characters. if inside any function then it is block whose cells contents are unknown (garbage/non-meaningful). [][][][][][][][][][] – The Mighty Programmer Dec 07 '13 at 18:52
0

The answer to my second question is that sizeof is a compiler time operator. therefore, he knows the size of defined array, like char abc[100]; But he doesn't really know the size of a pointer that points to array. like char *test = abc; I mean that the length of an array isn't saved in memory.

Weiner Nir
  • 1,435
  • 1
  • 15
  • 19
  • In most contexts, `sizeof()` is a compile-time operator. Under C99 with VLAs (variable length arrays), it is a run-time operator. – Jonathan Leffler Dec 07 '13 at 18:44
  • @Jonathan Leffler Is it true that the size of isn't saved in memory? – Weiner Nir Dec 07 '13 at 18:50
  • @Nirock That is true. The compiler knows the size of an array, but the information is gone once you start running the program. – David Heffernan Dec 07 '13 at 18:52
  • @JonathanLeffler Last question please! Why if I define array `char arr[100]`, I get random value for `arr[30]` for example? NOT RELEVANT ANYMORE, THANKS ANYWAY! – Weiner Nir Dec 07 '13 at 18:56