-3

How does sizeof() calculate that array1 is 3 bytes instead of 4 since I assigned a value to the 4th byte of memory allocated to the array?

#include <stdio.h>

char array1[3] = { 0,0,0 };
char array2[4] = { 0,0,0,0 };

char* a1 = array1;
char* a2 = array2;

int main(void) {
    printf("Array 1 Memory: %p\n", a1);
    printf("Array 2 Memory: %p\n\n", a2);

    //Array 1 set values and display addresses.
    printf("array1 = [");
    for (int i = 0; i < 5; i++) {
        array1[i] = i;
        printf("%d, ", array1[i]);
    }
    printf("\n");

    for (int i = 0; i < 4; i++) {
        printf("array1[%d] memory location: %p\n",i, a1 + i);
    }
    printf("size of array1 = %d\n", sizeof(array1));
    printf("]\n"); 

    //Array 2 display values and addresses
    printf("array2 = [");
    for (int i = 0; i < 4; i++) {
        printf("%d, ", array2[i]);
    }
    printf("\n");
    for (int i = 0; i < 4; i++) {
        printf("array2[%d] memory location: %p\n", i, a2 + i);
    }
    printf("size of array2 = %d\n", sizeof(array2));
    printf("]\n");

    printf("array2[-1] = %d\n", array2[-1]);

    return 0;
}

Array 1 Memory: 005CA4F4
Array 2 Memory: 005CA4F8

array1 = [0, 1, 2, 3, 4,
array1[0] memory location: 005CA4F4
array1[1] memory location: 005CA4F5
array1[2] memory location: 005CA4F6
array1[3] memory location: 005CA4F7
size of array1 = 3
]
array2 = [4, 0, 0, 0,
array2[0] memory location: 005CA4F8
array2[1] memory location: 005CA4F9
array2[2] memory location: 005CA4FA
array2[3] memory location: 005CA4FB
size of array2 = 4
]

array2[-1] = 3 //3 is stored in this location, so all bytes in the 4 byte word have a value in them. So //how does sizeof(array1) return a value of 3 instead of 4. How does it "remember" that only 3 bytes were //originally assigned to the array?

I looked for the declaration for the sizeof function in stdio header and couldn't find it. I thought that if I could see how sizeof() determines the size of an array, then it would give me some insight to my question. I'd like to know where sizeof() can be found.

Where is the source code for the C compiler that I can refer to in order to learn what an array actually is and how its size is stored in memory? If I create a char array[3], then a char[3] object is created, right? How is the char[3] object created? How does the system "remember" that the array should only be 3 bytes?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
ryanc
  • 1
  • 3
    `sizeof` is an operator, rather like `/` is an operator. There is no declaration for it. – Jonathan Leffler Jan 05 '23 at 01:31
  • 1
    [sizeof is an operator, not fuction](https://stackoverflow.com/q/1393582/995714), so obviously you can't find any declaration. You can use `sizeof var` without parentheses like a function – phuclv Jan 05 '23 at 01:36
  • 2
    You declared the first array to be of size 3. If you write beyond its boundary, you're writing outside the array, likely corrupting memory. – afarrag Jan 05 '23 at 01:36
  • 2
    Your code is exhibiting undefined behaviour. You are accessing elements not present in `array1` through the array `array1`. That is undefined behaviour. Anything can happen when you invoke undefined behaviour. – Jonathan Leffler Jan 05 '23 at 01:36
  • @phuclv: 'fuction' --> 'function' if you're quick. – Jonathan Leffler Jan 05 '23 at 01:37
  • Who is responsible for the bad “Community” Bot and how do we report errors by it? I have repeatedly seen it add a comment like this to question where there was enough detail to identify an adequate answer. What triggers it; there are no close votes visible nor prior comments that would seem to cue it? – Eric Postpischil Jan 05 '23 at 01:40
  • Re “Where is the source code for the C compiler”: There is no “the C compiler”; there are many C compilers. Diving into the source code is unlikely to be a good way to learn “what an array actually is and how its size is stored in memory?” An array’s size is often not stored anywhere in the memory of the subject program; it may exist only in the compiler process during compilation, except to the extent it might be deduced by circumstances (such as the location of the next external symbol after it). Learning C from a textbook is a better approach. – Eric Postpischil Jan 05 '23 at 01:43
  • @ryanc "... since I assigned a value to the 4th byte" --> Once an _array_ is defined, its size _cannot_ change. Code simply attempted to write outside the array - result _undefined behavior_, UB. – chux - Reinstate Monica Jan 05 '23 at 04:41

3 Answers3

2

Some useful links (highly recommended):

sizeof operator

Queries size of the object or type

Used when actual size of the object must be known

In C, there is no object creation per se but a definition of an declared object, more here:

Declarations

A declaration is a C language construct that introduces one or more identifiers into the program and specifies their meaning and properties.

Definitions

A definition is a declaration that provides all information about the identifiers it declares.

and

Array declaration

Array is a type consisting of a contiguously allocated nonempty sequence of objects with a particular element type. The number of those objects (the array size) never changes during the array lifetime.

and

Array initialization (e.g. Initialization from brace-enclosed lists)

Erdal Küçük
  • 4,810
  • 1
  • 6
  • 11
0

sizeof(array1) tells you how many bytes of memory were reserved for the object array1. It does not tell you how many bytes you attempted to store into it.

char array1[3] = { 0,0,0 }; reserves three bytes for array1.

array1[i] = i; attempts to write a byte to array1[i]. The C implementation generally does not check whether you are staying within the reserved memory or not. If you do not stay within the memory reserved for the array, the behavior is not defined by the C standard.

Using array1[i] = i; to write to memory outside the array does not change the reservation.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks for the explanation. Are the reserved bytes for an object stored in a register and the sizeof operator grabs the value from this register? Is there a way I could see the code for how the sizeof operator works? – ryanc Jan 05 '23 at 19:22
  • @ryanc: C is a compiler language. For ordinary objects, there is no `sizeof` in a running program. When the compiler is compiling, it replaces `sizeof x` with the size of `x`. The compiler knows the sizes of objects. (Except for variably modified types or objects of such types, there is a run-time issue, but this still amounts to generating an expression for the sizes, not calling some function named `sizeof` to compute the size or to retrieve it from storage.) – Eric Postpischil Jan 05 '23 at 19:41
0

A source of confusion for beginners is seeing sizeof() with parentheses and presuming it is a runtime function. It is not a runtime function. It is a "compile time" operator.

Parentheses are required when taking the size of a datatype:
eg: sizeof( char ) or sizeof( struct foobar ).

Parentheses are optional when taking the size of an item the compiler has already "seen" in the current "compilation unit" (typically meaning the current source file being compiled.) For example:

double a;
size_t size_of_a = sizeof a; // parentheses not required here.

Imagine that the expression "sizeof a" above is replaced with the value 8 (being the number of bytes used to store a single double floating point number in many compilers.)

The compiler has had to "measure" the storage requirements for your array. During compilation, the compiler "knows" the extent of that allocation and can quickly replace sizeof myarray with the correct value.

Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • Thanks for the information and for getting back to me. Does the compiler store the number of bytes for all objects in a register and then if you use the sizeof operator, it returns the value from the register for the object? If not, how does it "measure" the array size? I'm hoping I can see the code for the sizeof operator to understand more. – ryanc Jan 05 '23 at 19:26