A string literal is an array of characters* (with static storage), which contains all the characters in the literal along with a terminator. The size of an array is the size of the element multiplied by the number of elements in the array.
The literal "" is an array that consists of one char with the value 0. The type is char[1], and sizeof(char) is always one; thereforesizeof(char[1]) is always one.
In C, NULL is implementation-defined, and is often ((void*)0). The size of a void*, on your particular implementation, is 4. It may be a different number depending on the platform you run on. NULL may also expand to an integer of some type of the value 0, and you'd get the size of that instead.
*A literal is not a pointer, arrays are not pointers, pointers do not play a role in this part of the question.
Answer from GManNickG on Stack OverflowA string literal is an array of characters* (with static storage), which contains all the characters in the literal along with a terminator. The size of an array is the size of the element multiplied by the number of elements in the array.
The literal "" is an array that consists of one char with the value 0. The type is char[1], and sizeof(char) is always one; thereforesizeof(char[1]) is always one.
In C, NULL is implementation-defined, and is often ((void*)0). The size of a void*, on your particular implementation, is 4. It may be a different number depending on the platform you run on. NULL may also expand to an integer of some type of the value 0, and you'd get the size of that instead.
*A literal is not a pointer, arrays are not pointers, pointers do not play a role in this part of the question.
The empty string "" has type char[1], or "array 1 of char". It is not a pointer, as most people believe. It can decay into a pointer, so any time a pointer to char is expected, you can use an array of char instead, and the array will decay into a pointer to its first element.
Since sizeof(char) is 1 (by definition), we therefore have sizeof("") is sizeof(char[1]), which is 1*1 = 1.
In C, NULL is an "implementation-defined null pointer constant" (C99 §7.17.3). A "null pointer constant" is defined to be an integer expression with the value 0, or such an expression cast to type void * (C99 §6.3.2.3.3). So the actual value of sizeof(NULL) is implementation-defined: you might get sizeof(int), or you might get sizeof(void*). On 64-bit systems, you often have sizeof(int) == 4 and sizeof(void*) == 8, which means you can't depend on what sizeof(NULL) is.
Also note that most C implementations define NULL as ((void*)0) (though this is not required by the standard), whereas most C++ implementations just define NULL as a plain 0. This means that the value of sizeof(NULL) can and will change depending on if code is compiled as C or as C++ (for example, code in header files shared between C and C++ source files). So do not depend on sizeof(NULL).
sizeof is an operator, not a function.
You would be reminded of this if you dropped the pointless parentheses, and just wrote it:
printf("%zu", sizeof *abcp);
This also uses the C99-proper way to format a value of type size_t, which is %zu.
It works since the compiler computes the size at compile-time, without ever following (dereferencing) the pointer of course (since the pointer doesn't yet exist; the program isn't running).
sizeof is not a function and it doesn't evaluate its argument. Instead it deduces the type of *abcp, at compile time, and reports the size of that. Since abcp is a struct abc*, the type of *abcp is struct abc regardless of where abcp points.
In this Stackoverflow post[1] is stumbled upon a 'trick' to get the size of struct members like so: sizeof(((struct*)0)->member) which I struggle to comprehend what's happening here.
what I understand:
- sizeof calculates the size, as normal
- ->member dereferences as usual
what I don't understand:
- (struct*) 0 is a typecast (?) of a nullptr (?) to address 0 (?)
Can someone dissect this syntax and explain in detail what happens under the hood?
[1] https://stackoverflow.com/a/3553321/18918472
I was skimming the Linux coding style guide just now and saw this:
The preferred form for passing a size of a struct is the following:
p = kmalloc(sizeof(*p), ...);
The alternative form where struct name is spelled out hurts readability and introduces an opportunity for a bug when the pointer variable type is changed but the corresponding sizeof that is passed to a memory allocator is not.
When I read that I was like, "oh that makes sense, I'll do that!" but then I thought, wait, what if the pointer has already been initialized to NULL. Is it undefined behavior? My understanding is that sizeof() doesn't actually access the value, so there won't be a dereference. Am I wrong?
sizeof(a) gives you the size of the pointer, not of the array of characters the pointer points to. It's the same as if you had said sizeof(char*).
You need to use strlen() to compute the length of a null-terminated string (note that the length returned does not include the null terminator, so strlen("abcd") is 4, not 5). Or, you can initialize an array with the string literal:
char a[] = "abcd";
size_t sizeof_a = sizeof(a); // sizeof_a is 5, because 'a' is an array not a pointer
The string literal "abcd" is null terminated; all string literals are null terminated.
You get 4 because that's the size of a pointer on your system. If you want to get the length of a nul terminated string, you want the strlen function in the C standard library.
The sizeof operator is evaluated at compile time. Its operand is not evaluated for side effects, so your program is safe. This is guaranteed by the standard 6.5.3.4/2 (emphasis mine):
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 that there is a special case of variable length arrays, in which case the evaluation takes place in run time, so code de-referencing an invalid pointer to a VLA inside sizeof would not be safe.)
As a side note, the correct format specifier for printf when printing the result of sizeof is %zu (the result of sizeof is type size_t).
Because sizeof(exp) is a compile time operator, and it does not evaluate expression exp at run-time.
As a result, there is no dereference of NULL pointer at run-time. You just have equivalent machine code of a constant in your printf statement in your final binary.
0 being an int like other integers, sizeof(0) will yield 4 bytes.
sizeof(NULL) will yield 8 bytes. In binary system, it is 8x8=64 bits, all bits with 0.
Pointers have 8 bytes allocated against characters with 1 bytes and integers 4 bytes. Is 8 bytes the maximum bytes for any datatype? I believe so as NULL is set to 8 bytes apparently for that reason to take care NULL denotes 0 for all datatypes.
I know that in usual for strings, sizeof() and strlen() return values that differ by 1, because sizeof() is counting the null terminator, whereas strlen() isn't. But I'm trying to understand the discrepancy between sizeof() and strlen() that arises when I allocate a 5-character string into a char[5] array that doesn't have room for the null-terminator.
#include <stdio.h>
#include <string.h>
int main(){
char c[5] = "hello";
char d[] = "hello";
printf("Sizeof is %lu, and strlen is %lu.\n",sizeof(c),strlen(c));
printf("Sizeof is %lu, and strlen is %lu.\n",sizeof(d),strlen(d));
}
Output:
Sizeof is 5, and strlen is 5
Sizeof is 6, and strlen is 5
I find this a bit confusing. If I do char[4] = "hello";, then I get a compiler warning for the "hello" being bigger than char[4]. But in reality, "hello" should also be bigger than char[5] too, right?
The first line reporting sizeof is 5 and strlen is 5 seems to be consistent with the char[5] declaration just omitting the null-terminator, but the fact that strlen() in the second line is just returning 5 instead of a bunch of junk from the lack of a null-terminator is odd.
Any thoughts?
Thanks.