the size of dynamically allocated array in C [duplicate] - c

This question already has answers here:
Behavior of sizeof on variable length arrays (C only)
(2 answers)
Closed 5 years ago.
I know that this question has been asked before, but my question is more specific,
here is the code:
#include <stdio.h>
#include <time.h> /* must be included for the time function */
main()
{
time_t t = time(NULL);
srand((unsigned) t);
int i = rand();
int a[i];
printf("%d\n", i); /* ouptut: 18659 */
printf("%d\n", sizeof a); /* output: 74636 */
}
I compiled this code using gcc and -ansi option to restrict it to recognize the ANSI C only.
I know that there is no way that the compiler could know at compile-time the size of the array because it's determined randomly at run-time.
Now my question is is the value returned by sizeof is just a random value, or it has a meaning?

The sizeof operator is evaluated at compile time for most operands. In the case of a VLA, it is evaluated at runtime.
From section 6.5.3.4 of the C standard:
2 The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The
size is determined from the type of the operand. The result is an
integer. 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
So the size returned by sizeof is the size in bytes of the VLA. In your example, that would be i * sizeof(int)

The value returned by sizeof is a pseudo-random value that has a meaning:
The value represents the size of VLA a, in bytes
It is random only in the sense that the number of array elements is determined by a call to rand.
It appears that sizeof(int) on your system is 4, because the number returned by sizeof is four times the number of elements in the array.
Note: One of the consequences of allowing VLAs in C99 is that sizeof is no longer a purely compile-time expression. When the argument of sizeof operator is a VLA, the result is computed at run-time.

From the gcc manual
The -ansi option does not cause non-ISO programs to be rejected gratuitously. For that, -Wpedantic is required in addition to -ansi.

is the value returned by sizeof is just a random value, or it has a meaning?
It does have a meaning, as 74636 / 18659 = 4, which apparently is the size of int on your machine.
So sizeof (which will be computed at run-time instead of compile-time since the argument is a VLA), will return the size of array a in bytes, which is the number of ints it contains (in other words i or 18659) multiplied by the size of int, which is 4 on your machine.
As i (the result of rand) is random, you can consider that the value of sizeof will be random too in that sense.

Related

What's the correct way to use scanf_s in using string arrays?

char array1[10];
scanf_s("%9s", array1, (unsigned)_countof(array1);
What's mean of (unsigned)_countof(array1)?
and what's different from use scanf_s("%9s", array1, sizeof(array1);?
both worked, but I want to understand about it more surely
What's the correct way to use scanf_s in using string arrays?
scanf_s() with "%9s" is not for string arrays. It is for reading text and saving as a single string, which is a character array with a null character.
Its proper use is complicated by MSVC expects a different type in the count argument than C11. In C11 and later, scanf_s() is an optional function of the standard library and lacks wide acceptance.
// MSVC - type unsigned expected, hence the cast.
scanf_s("%9s", array1, (unsigned)_countof(array1);
// C11 - type size_t expected
scanf_s("%9s", array1, sizeof array1 / sizeof array1[0]);
Proper use of either obliges code to check the return value of scanf_s()
if (1 == scanf_s("%9s", ...)) Success();
else Fail();
What's mean of (unsigned)_countof(array1)?
_countof() is an MSVC macro equivalent to (sizeof(array) / sizeof(array[0])). When passed an array, it returns the count of elements in the array as type size_t. Casting to unsigned gets the expected type as with MSVC scanf_s(). The value may truncate due to the cast - a rare issue with huge arrays.
what's different from use scanf_s("%9s", array1, sizeof(array1));?
The expected type of sizeof(array1) is size_t and not unsigned as expected in MSVC - leading to undefined behavior. When size_t is as unsigned, that is OK, else a real problem.
The conceptual value is wrong. It should be the array element count, not the byte size of the array. Either OK here as sizeof(char)==1, yet wrong if code moved to say using wide characters.
both worked
Code is not portable. It may have "worked" in OP's case, but lacks portability.
Consider alternatives to scanf_s(), scanf() like fgets().
sizeof and _countof are different.
(edit:) In this case you should use countof.
sizeof is an operator in C that returns the memory size occupied by a variable, in bytes.
In this case, array1 is an array of 10 chars, so it's size is ten times the size of a char, and sizeof(char) is 1 byte. So the value of sizeof(array1) is 10 * 1 = 10 bytes.
Note that in C you can use sizeof on any variable (e.g. sizeof(array1)) or on any type (e.g. sizeof(int)).
_countof is a macro (only available on Microsoft platforms) that gives you the number of elements declared in an array variable. In this case your array1 variable has 10 elements, so _countof(array1) will be 10.
Now in your precise case this happens to be the same result because the size of each char is 1, but this wouldn't be the same if, for example, your variable was an array of ints.
int array2[10];
sizeof(array2); // = 40
_countof(array2); // = 10
An int is (usually) 4 bytes, so an array of 10 ints will have a size of 10*4 = 40 bytes. On the other hand, _countof will just count how many elements are declared in the array, and still return 10.
In fact, we can see that the definition of _countof is litterally sizeof(array) divided by sizeof(array[0]), that is, the size of an individual element.
Since scanf_s with "%s" expects a number of items, you should be using _countof. (edit).
You might also want to be careful with sizeof (and _countof) on arrays, and avoid using them on pointers. Also be aware that _countof will not work outside of Visual Studio. See these related answers.
This question is compiler based, GCC 11.1.0 on Arch Linux does not have functions like scanf_s and _countof. These functions/macros might be valid in Windows.
I read some docs on Microsoft docs. So, _countof is a macro which calls sizeof() internally and scanf_s is similar to scanf in standard C17.
What's mean of (unsigned)_countof(array1)? and what's different from use scanf_s("%9s", array1, sizeof(array1);? both work, but I want to understand about it more surely
Here the macro _countof is counting the length of the stack stored array, which in this case is 10.
_countof macro expands to:
#define _countof(x) (sizeof(x) / sizeof(x[0]))
// the operation goes for `array1` like this:
// 10 * 1 byte / 1 byte
// 1 byte is the sizeof char
// hence, 10 is returned as the result of the above operation
And (unsigned) is just type casting the value of the above operation.
NOTE: As _countof is calling sizeof() do not use this inside a function the get the length of an array. Because sizeof(arr_ptr) will return the size of pointer which is 8 bytes in my case (x86_64 architecture).
Conclusion:
There no _countof is just calling sizeof(). I would like to suggest you to use sizeof and scanf functions because they are cross-platform and portable throughout the C standards.

Explanation of output of program

Can anyone explain why this program prints 4 1 instead of 4 2?
Shouldn't pre increment operator which has higher precedence get executed first and print 4 2?
#include <stdio.h>
int main() {
int a=1;
printf ("%ld %d",sizeof(++a),a);
return 0;
}
Although you've already gotten several answers, I want to provide one more, because your question actually contained three separate misunderstandings, and I want to touch on all of them.
First of all, sizeof is a special operator which, by definition, does not evaluate its argument (that is, whatever subexpression it's taking the size of). So sizeof(++a) does not increment a. And sizeof(x = 5) would not assign 5 to x. And sizeof(printf("Hello!")) would not print "Hello".
Second, if we got rid of the sizeof, and simply wrote
printf("%d %d", ++a, a);
we would not be able to use precedence to figure out the behavior. Precedence is an important concept, but in general it does not help you figure out the behavior of confusing operations involving ++.
Finally, the perhaps surprising answer is that if you write
printf("%d %d", ++a, a);
it is not possible to figure out what it will do at all. It's basically undefined. (Specifically: in any function call like printf("%d %d", x, y) it's unspecified which order the arguments get evaluated in, so you don't know whether x or y gets evaluated first -- although there is an order. But then, when one of them is a and one of them is ++a, you have a situation where a is both being modified and having its value used, so there's no way to know whether the old or the new value gets used, and this makes the expression undefined. See this question for more on this issue.)
P.S. One more issue I forgot to mention, as noted by #Vlad from Moscow: %ld is not a reliable way to print the result of sizeof, which is a value of type size_t. You should use %zu if you can, or %u after casting to (unsigned) if you can't.
From the C Standard *6.5.3.4 The sizeof and alignof operators)
2 The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer. 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.
So the task of the sizeof operator is to determine the type of the expression used as an operand and then knowing the type of its operand to return the size of an object of the type. If the operand is not a variable length array then the expression used as an operand is not evaluated and the value returned by the sizeof operator is calculated at compile-time.
Thus this call
printf ("%ld %d",sizeof(++a),a);
is equivalent to the call
printf ("%ld %d",sizeof( int ),a);
and in your system sizeof( int ) is equal to 4.
So it does not matter what expression is used (except using a variable length array the size of which is calculated at run time) as an operand. It is the type of the expression that is important. For example you could even write
printf ( "%zu %d\n", sizeof( ( ++a, ++a, ++a, ++a, ++a ) ), a );
and got the same result.
Pay attention to that you should use the conversion specifier zu used for values of the type size_t instead of ld used for signed values. That is you need to write
printf ("%zu %d",sizeof(++a),a);
According to c99 standard,
the sizeof() operator only takes into account the type of the operand, which may be an expression or the name of a type (i.e int, double, float etc) and not the value obtained on evaluating the expression.
Hence, the operand inside the sizeof() operator is not evaluate.

How does sizeof operator behaves in below code snippet?

Please explain the OP for below code snippet :
int *a="";
char *b=NULL;
float *c='\0' ;
printf(" %d",sizeof(a[1])); // prints 4
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4
Compiler interprets a[1] as *(a+1) , so a has some address , now it steps 4 bytes ahead , then it will have some garbage value there so how is the OP 4 bytes , even if I do a[0] , still it prints 4 , although it is an empty string , so how come its size is 4 bytes ?
Here we are finding out the size of the variable the pointer is pointing to , so if I say size of a[1] , it means size of *(a+1), Now a has the address of a string constant which is an empty string , after I do +1 to that address it moves 4 bytes ahead , now its at some new address , now how do we know the size of this value , it can be an integer , a character or a float , anything , so how to reach to a conclusion for this ?
The sizeof operator does not evaluate its operand except one case.
From the C Standard (6.5.3.4 The sizeof and alignof operators)
2 The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer.
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.
In this code snippet
int *a="";
char *b=NULL;
float *c='\0' ;
printf(" %d",sizeof(a[1])); // prints 4
printf(" %d",sizeof(b[1])); // prints 1
printf(" %d",sizeof(c[1])); // prints 4
the type of the expression a[1] is int, the type of the expression b[1] is char and the type of the expression c[1] is float.
So the printf calls output correspondingly 4, 1, 4.
However the format specifiers in the calls are specified incorrectly. Instead of "%d" there must be "%zu" because the type of the value returned by the sizeof operator is size_t.
From the same section of the C Standard
5 The value of the result of both operators is implementation-defined,
and its type (an unsigned integer type) is size_t, defined in
<stddef.h> (and other headers).
This is all done statically, i.e. no dereferencing is happening at runtime. This is how the sizeof operator works, unless you use variable-length arrays (VLAs), then it must do work at runtime.
Which is why you can get away with sizeof:ing through a NULL pointer, and other things.
You should still be getting trouble for
int *a = "";
which makes no sense. I really dislike the c initializer too, but at least that makes sense.
sizeof operator happens at compilation (except for VLA's). It is looking at the type of an expression, not the actual data so even something like this will work:
sizeof(((float *)NULL)[1])
and give you the size of a float. Which on your system is 4 bytes.
Live example
Even though this looks super bad, it is all well defined, since no dereference ever actually occurs. This is all operations on type information at compile time.
sizeof() is based on the data type, so whilst it's getting the sizes outside the bounds of memory allocated to your variables, it doesn't matter as it's worked out at compile time rather than run time.

Using multiplied macro in array declaration

I know the following is valid code:
#define SOMEMACRO 10
int arr[SOMEMACRO];
which would result as int arr[10].
If I wanted to make an array 2x size of that (and still need the original macro elsewhere), is this valid code?
#define SOMEMACRO 10
int arr[2 * SOMEMACRO];
which would be int arr[2 * 10] after precompilation. Is this still considered as constant expression by the compiler?
After a quick look it seems to work, but is this defined behavior?
Yes it will work.MACRO will be placed as it is at compilation so a[2*SOMEMACRO] will become a[2*10] which is perfectly valid.
To check what is preprocessed you can use cc -E foo.c option
Is this still considered as constant expression by the compiler?
Yes. That's the difference between a constant expression and a literal: a constant expression need not be a single literal, bit it can be any expression of which the value can be computed at compile time (i. e. a combination of literals or other constant expressions).
(Just for the sake of clarity: of course literals are still considered constant expressions.)
However, in C, the size of the array need not be a compile-time constant. C99 and C11 supports variable-length arrays (VLAs), so
size_t sz = // some size calculated at runtime;
int arr[sz];
is valid C as well.
Yes you can use this expression. It will not result in UB.
Note that an array subcript may be an integer expression:
#define i 5
#define j 4
int a[i+j*10] = 0;
The value of of subscript i+j*10 will be calculated during compilation.
yes, as long as it a valid number it's a constant expression.
and if you say it worked then you know the compiler worked just fine with it.
as you know we can't do
int x;
scanf("%d", &x);
int arr[2 * x];
because that's no a constant number. but what you've written is a constant number, so you're good to go

Using ++ inside the sizeof keyword [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
what's the mechanism of sizeof() in C/C++?
Hi,
I'm a TA for a university, and recently, I showed my undergraduate students the following C code from a C puzzle I found:
int i = 5;
int j = sizeof(i++);
printf("%d\n%d\n", i, j);
I just have one question: why is the output for i equal to 5, not 6? Is the ++ simply disregarded? What's going on here? Thanks!
The expression in a sizeof is not evaluated - only its type is used. In this case, the type is int, the result of what i++ would produce if it were evaluated. This behavior is necessary, as sizeof is actually a compile-time operation (so its result can be used for things like sizing arrays), not a run-time one.
The sizeof operator is evaluated at compile-time. sizeof(i++) basically reads to the compiler as sizeof(int) (discarding the ++).
To demonstrate this you can look at the assembly view of your little program:
As you can see in the marked line, the size of the integer (4) is already there and just loaded into i. It is not evaluated or even calculated when the program runs.
Yes, inside sizeof is only evaluated for the type.
The main reason is that sizeof is not a function, it is an operator. And it is mostly evaluated at compile-time unless there is a variable length array. Since int's size can be evaluated at compile-time, therefore, it returns 4.
why is the output for i equal to 5, not 6?
sizeof does not evaluate the expression inside it, only the type.
What we have keep in mind is that sizeof is not a function but a compile time operator, so, it is impossible for it evaluate its content.

Resources