c programming, How can i get the sizeof a variable through a function using a pointer as a parameter? - Stack Overflow
How sizeof works in C/C++
c - sizeof style: sizeof(type) or sizeof variable? - Software Engineering Stack Exchange
How do I determine the size of my array in C? - Stack Overflow
Videos
You can't just ask for sizeof(pointer) since you'll get the size of the pointer itself. Instead of that- you can change the function to get the size as parameter:
readEachChar(unsigned char * input, unsigned size)
and send the size from main:readEachChar(&text, sizeof(text));
Another solution is to run over the char until you reach the null - '\0' at the end and count the characters within it- that's what the strlen function does.
In the line
printf("The the size of the string %zu", sizeof(input));
the sizeof operator will give you the size of the pointer input. It will not give you the size of the object that it is pointing to (which may be the size of the array or the length of the string).
In the function main, the definition
unsigned char text[] = "thisisalongkindofstring";
will make text an array of 24 characters: These 24 characters consist of the 23 actual characters and an extra character for the null terminating character. In C, a string is, by definition, a sequence of characters that is terminated by a null character, i.e. a character with the character code 0.
Therefore, in order to determine the length of the string, you must count every character of the string, until you encounter the terminating null character. You can either do this yourself, or you can use the function strlen which is provided by the C standard library.
Also, it is normal to use the data type char for individual characters of a string, not unsigned char. All string handling functions of the C standard library expect parameters of type char *, not unsigned char *, so, depending on your compiler, mixing these data types could give you warnings or even errors.
Another issue is that this line is wrong:
readEachChar(&text);
The function readEachChar seems to expect the function argument to be a pointer to the first character of the string, not a pointer to an entire array. Therefore, you should write &text[0] instead of &text. You can also simply write text, as this expression will automatically decay to &text[0].
After applying all of the fixes mentioned above, your code should look like this:
#include <stdio.h>
#include <string.h>
void readEachChar( char * input )
{
size_t len = strlen( input );
printf( "The size of the string: %zu\n", len );
for ( size_t i = 0; i < len; i++ )
{
printf( "[%x]", input[i] );
}
printf("\n");
}
int main()
{
char text[] = "thisisalongkindofstring";
readEachChar( text );
return 0;
}
This program has the following output:
The size of the string: 23
[74][68][69][73][69][73][61][6c][6f][6e][67][6b][69][6e][64][6f][66][73][74][72][69][6e][67]
I perfer sizeof(variable) over sizeof(type). Consider:
int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));
vs.
int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));
In the first case, it's easy to verify that the right sizes are being passed to memset. In the second case, you need to constantly review top and bottom sections to make sure you are consistent.
The preference (as always) is to reflect your intention as directly as possible.
Is the intention to operate against an existing variable's memory? If so, then use sizeof(variable), as this shows as closely as possible that it's the variable itself's memory that you care about.
Is the intention to perform some calculation on the type, for example to determine how much memory should be allocated for a new instance? If so, then use sizeof(type).
That is, I prefer
struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));
over
bar = (struct foo *) malloc(sizeof(*bar));
as the latter case looks like you're trying to access a variable that doesn't exist, yet.
On the other hand, I prefer
char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));
over
char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));
as the intention is clearly to zero-fill the contents of the variable, so it's the variable we should operate against. Trying to use the type metadata just confuses things, here.
Executive summary:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
Full answer:
To determine the size of your array in bytes, you can use the sizeof
operator:
int a[17];
size_t n = sizeof(a);
On my computer, ints are 4 bytes long, so n is 68.
To determine the number of elements in the array, we can divide the total size of the array by the size of the array element. You could do this with the type, like this:
int a[17];
size_t n = sizeof(a) / sizeof(int);
and get the proper answer (68 / 4 = 17), but if the type of
a changed you would have a nasty bug if you forgot to change
the sizeof(int) as well.
So the preferred divisor is sizeof(a[0]) or the equivalent sizeof(*a), the size of the first element of the array.
int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
Another advantage is that you can now easily parameterize the array name in a macro and get:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int a[17];
size_t n = NELEMS(a);
The sizeof way is the right way iff you are dealing with arrays not received as parameters. An array sent as a parameter to a function is treated as a pointer, so sizeof will return the pointer's size, instead of the array's.
Thus, inside functions this method does not work. Instead, always pass an additional parameter size_t size indicating the number of elements in the array.
Test:
#include <stdio.h>
#include <stdlib.h>
void printSizeOf(int intArray[]);
void printLength(int intArray[]);
int main(int argc, char* argv[])
{
int array[] = { 0, 1, 2, 3, 4, 5, 6 };
printf("sizeof of array: %d\n", (int) sizeof(array));
printSizeOf(array);
printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
printLength(array);
}
void printSizeOf(int intArray[])
{
printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}
void printLength(int intArray[])
{
printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}
Output (in a 64-bit Linux OS):
sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2
Output (in a 32-bit windows OS):
sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
sizeof isn't a function, it's a keyword. You could drop the parentheses and it would work just fine. Because it's not a function, it works with any type or object that you give it - it's much more flexible than a function.
sizeof is not a function; it's an operator. It can be used in two ways: as sizeof(typename) and as sizeof expression. The parentheses are required when used with a type name. Parentheses are not needed when the operand is an expression, though for clarity's sake many programmers will parenthesize the expression regardless. Note that unlike most programming languages operators, sizeof expression does not evaluate its argument under normal circumstances, i.e., when its operand is not a C99 variable-length array.
1. My previous knowledge suggested that it is a compile-time operator, which I never questioned, because I never abused sizeof too much…
C 2018 6.5.3.4 2 specifies the behavior of sizeof and says:
… 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 your example with sizeof(int[size]), the type of int[size] is a variable length array type, so the operand is evaluated1, effectively computing the size during program execution.
In your example with sizeof(*p), the type of *p is not a variable length array type, so the operand is not evaluated. The fact that p may point to an object of automatic storage duration that is created during program execution is irrelevant; the type of *p is known during compilation, so *p is not evaluated, and the result of sizeof is an integer constant.
2. Does sizeof return a value of type int, is it a size_t (ULL on my platform), or is it implementation-defined.
C 2018 6.5.3.4 5 says “The value of the result of both operators [sizeof and _Alignof] is implementation-defined, and its type (an unsigned integer type) is size_t, defined in <stddef.h> (and other headers).”
3. This article states that "The operand to sizeof cannot be a type-cast", which is incorrect. Type-casting has the same precedence as the sizeof operator, meaning in a situation where both are used, they are simply evaluated right to left.
sizeof(int) * p probably does not work, because if the operand is a type in braces, this is handled first, but sizeof((int)*p) works just fine.
The article means the operand cannot directly be a cast-expression (C 2018 6.5.4) in the form ( type-name ) cast-expression, due to how the formal grammar of C is structured. Formally, an expression operand to sizeof is a unary-expression (6.5.3) in the grammar, and a unary-expression can, through a chain of grammar productions, be a cast-expression inside parentheses.
Footnote
1 We often think of a type-name (a specification of a type, such as int [size]) as more of a passive declaration than an executable statement or expression, but C 2018 6.8 4 tells us “There is also an implicit full expression in which the non-constant size expressions for a variably modified type are evaluated…”
The semantics of sizeof() per the (draft) C11 standard:
The
sizeofoperator 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.
Note "If the type of the operand is a variable length array type, the operand is evaluated". The means that the size of a VLA is computed at run time.
"otherwise, the operand is not evaluated and the result is an integer constant" means the result is evaluated at compile time.
The return type is size_t. Full stop:
The value of the result of both operators (
sizeof()and_Alignof()) is implementation-defined, and its type (an unsigned integer type) issize_t, defined in <stddef.h> (and other headers).
Note that the type is size_t. Don't use unsigned long nor unsigned long long nor anything else. Always use size_t.