Interview question about various pointer size under 32bit architecture - c

char str[] = " http://www.ibegroup.com/";
char *p = str ;
void Foo ( char str[100]){
}
void *p = malloc( 100 );
What's the sizeof str,p,str,p in the above 4 case in turn?
I've tested it under my machine(which seems to be 64bit) with these results:
25 8 8 8
But don't understand the reason yet.

sizeof(char[]) returns the number of bytes in the string, i.e. strlen()+1 for null-terminated C strings filling the entire array. Arrays don't decay to pointers in sizeof. str is an array, and the string has 25 characters plus a null byte, so sizeof(str) should be 26. Did you add a space to the value?
The size of a pointer is of course always determined just by the machine architecture, so both instances of p are 8 bytes on 64-bit architectures and 4 bytes on 32-bit architectures.
In function arguments, arrays do decay to pointers, so you're getting the same result that you get for a pointer. Therefore, the following definitions are equivalent:
void foo(char s[42]) {};
void foo(char s[100]) {};
void foo(char* s) {};

The first is the sizeof of an built-in array, which is the amount of elements (24 + null on the end of the string).
The second is the sizeof of a pointer which is the native word size of your system, in your case 64 bit or 8 bytes.
The third is the sizeof of a pointer to the first element of an array which has the same size as any other pointer, the native word size of your system. Why a pointer to the first element of an array? Because size information of an array goes lost when passed to a function and it gets implicitly converted to a pointer to the first element instead.
The fourth is the sizeof of a pointer which has the same size as any other pointer.

str is an array of 8-bit characters, including null terminator.
p is a pointer, which is typically the size of the machine's native word size (32 bit or 64 bit).
The size taken up by a pointer stays constant, regardless of the size of the memory to which it points.
EDIT
In c++, arguments that are arrays are passed by reference (which internally is a pointer type), that's why the second instance of str has sizeof 8.

in the cases the size of
char str[] = “ http://www.ibegroup.com/”
is known to be 25 (24+1), because that much memory is actually allocated.
In the case of
void Foo ( char str[100]){
no memory is allocated

Related

Why strtok_r break string at '.'(peroid) instead of ',' (comma)? [duplicate]

I have a piece of C code and I don't understand how the sizeof(...) function works:
#include <stdio.h>
int main(){
const char firstname[] = "bobby";
const char* lastname = "eraserhead";
printf("%lu\n", sizeof(firstname) + sizeof(lastname));
return 0;
}
In the above code sizeof(firstname) is 6 and sizeof(lastname) is 8.
But bobby is 5 characters wide and eraserhead is 11 wide. I expect 16.
Why is sizeof behaving differently for the character array and pointer to character?
Can any one clarify?
firstname is a char array carrying a trailing 0-terminator. lastname is a pointer. On a 64bit system pointers are 8 byte wide.
sizeof an array is the size of the total array, in the case of "bobby", it's 5 characters and one trailing \0 which equals 6.
sizeof a pointer is the size of the pointer, which is normally 4 bytes in 32-bit machine and 8 bytes in 64-bit machine.
The size of your first array is the size of bobby\0. \0 is the terminator character, so it is 6.
The second size is the size of a pointer, which is 8 byte in your 64bit system. Its size doesn't depends on the assigned string's length.
how the sizeof(...) function works
sizeof() looks like a function but it's not a function. A function computes something at run-time.
sizeof() asks the compiler, at compile-time, how much memory it allocates for the argument. BTW sizeof() has no idea how much of it you actually use later at run time. In other words, you've "hardcoded" the printf arguments in your example.
Why is sizeof behaving differently for the character array and pointer
to character?
A pointer rarely requires the same amount of memory as an array.
In general, the amount of memory allocated for a pointer is different to what is allocated for its pointee.
firstname is an array of 6 chars, including the terminating '\0' character at the end of the string. That's why sizeof firstname is 6.
lastname is a pointer to char, and will have whatever size such a pointer has on your system. Typical values are 4 and 8. The size of lastname will be the same no matter what it is pointing to (or even if it is pointing to nothing at all).
firstname[] is null-terminated, which adds 1 to the length.
sizeof(lastname) is giving the size of the pointer instead of the actual value.

Size of pointer, pointer to pointer in C

How can I justify the output of the below C program?
#include <stdio.h>
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
char *a;
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main(void) {
printf("%d %d %d %d ",sizeof(a),sizeof(c),sizeof(cp),sizeof(cpp));
return 0;
}
Prints
4 16 16 4
Why?
Here is the ideone link if you want to fiddle with it.
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
c is an array of char* pointers. The initializer gives it a length of 4 elements, so it's of type char *[4]. The size of that type, and therefore of c, is 4 * sizeof (char*).
char *a;
a is a pointer of type char*.
char **cp[] = {c+3, c+2, c+1, c};
cp is an array of char** pointers. The initializer has 4 elements, so it's of type char **[4]. It size is 4 * sizeof (char**).
char ***cpp = cp;
cpp is a pointer to pointer to pointer to char, or char***. Its size is sizeof (char***).
Your code uses %d to print the size values. This is incorrect -- but it happens to work on your system. Probably int and size_t are the same size. To print a size_t value correctly, use %zu -- or, if the value isn't very large, you can cast it to int and use %d. (The %zu format was introduced in C99; there might still be some implementations that don't support it.)
The particular sizes you get:
sizeof a == 4
sizeof c == 16
sizeof cp == 16
sizeof cpp == 4
are specific to your system. Apparently your system uses 4-byte pointers. Other systems may have pointers of different sizes; 8 bytes is common. Almost all systems use the same size for all pointer types, but that's not guaranteed; it's possible, for example, for char* to be larger than char***. (Some systems might require more information to specify a byte location in memory than a word location.)
(You'll note that I omitted the parentheses on the sizeof expressions. That's legal because sizeof is an operator, not a function; its operand is either an expression (which may or may not be parenthesized) or a type name in parentheses, like sizeof (char*).)
a is an usually pointer, which represents the memory address. On 32-bit operating system, 32bit (4 Byte) unsigned integer is used to represent the address. Therefore, sizeof(a) is 4.
c is an array with 4 element, each element is a pointer, its size is 4*4 = 16
cp is also an array, each element is a pointer (the first *, wich point to another pointer (the second *). The later pointer points to an string in the memory. Therefore its basic element size should represent the size of a pointer. and then sizeof(cp) = 4*4 = 16.
cpp is a pointer's pointer's pointer. It is as well represent the 32bit memory address. therefore its sizeof is also 4.
a is a pointer. cpp is also a pointer just to different type (pointer to pointer to pointer).
Now c is an array. You have 4 elements, each is a pointer so you have 4 * 4 = 16 (it would be different if you would run it on x64).
Similar goes for cp. Try changing type to int and you will see the difference.
So the reason you got 4 16 16 4, is because 'a' is simply a pointer, on its own, which only requires 4 bytes (as a pointer is holding a 32bit address depending on your architecture) and so when you have a **pointer which is == to a *pointer[], your really making an array of pointers, and since you initalized 4 things that created 4 pointers, thus the 4x4 = 16. And for the cpp you may ask "well wouldn't it then be 16 as it was initalized?" and the answer is no, because a ***pointer is its own separate variable and still just a pointer(a pointer to a pointer to a pointer, or a pointer to an array of pointers), and requires only 4bytes of memory.

Why I am getting this decimal int in this char?

I am starting C before learned Python and i am having some doubts in some concepts.
I am running this example in a 64-bit machine.
/* I understand that "vid" is only a char like any other else not a array of char
and its sizeof is 1 byte. The decimal int is 100 and the char is 'D'.
Why? 'vid' does not exist in ASCII table. How does the compiler leads with that */
char name = "vid";
/* sizeof is 8 bytes. I am not sure because if char is int therefore an array
of char would
be an array of int and if so int takes 2 or 4 bytes storage size so we reach that is
3 char long plus the NULL byte ('\0') we get 3 * 2 bytes + 1 * 2 bytes = 8 bytes .
Am i correct? And why we need to use * to declare it? Does * is not for pointers?
How does this syntax works? */
char *name_ = "vid";
A string constant like "vid" decays into a pointer to its first byte, and when you convert a pointer to a char, the program will truncate the pointer's value to make it fit. Apparently, that happens to produce a number whose ASCII value is D on your machine. You get an initialization makes integer from pointer without a cast warning for that, if you compile with GCC.
sizeof(name_) == sizeof(char*), which is 8 on a machine with 64-bit pointers. sizeof("vid") == 4, per definition: sizeof measures size in char units.
In the first exemple name = "vid" you are not assigning the string "vid" to name, by convension, a string constant is a pointer to it's first element, so in the first statment you're assigning the address of "vid". Like others said by accident the number stored in name after the address gets fitted to 1 bytes was the ascii code of 'D'. But if you turn on warnings you will get an error message telling you that your tring to assigne make a char from char * which is not compatible as char can hold only 1 byte.
The second exemple char *name_ = "vid" your assigning the address of "vid" to name_ which is right as it is a pointer to char.
Note that you are not storing the string "vid" in name_. The string constant "vid" is stored somewhere in a read only memory and the address of the first element of that string constant is assigned to name_.
For your first example, I am not sure how that compiles. You are attempting to assign an array of characters to a single character. This shouldn't be allowed without some kind of warning.
For the second, you are taking sizeof a char*, which is a pointer. Anytime you add the * to a type, you make it a pointer. In your case, this is 8 bytes, regardless of how much data it is pointing to. If you want to know the size of the data and not the size of the pointer, then you'd need to do the following;
sizeof(name_[0]) * 4
or
sizeof(char) * 4
Since your array is 3 characters, +1 for the null character, making it 4 characters long. This takes the size of the first element (a single character, 1 byte) and multiplies it by the length of the string. Thus, your data size should be 4 bytes.
Your first string of code declares name as a pointer to an array of four characters placed in static data segment. So when you are treating name as a character you get the last byte of the pointer: 0x??????????????64 where '??' are unknown bytes.
About the second string, you're getting sizeof of the pointer. In 64-bit systems pointers are 64-bit or 8-byte. It is what you get.

size of character array and size of character pointer

I have a piece of C code and I don't understand how the sizeof(...) function works:
#include <stdio.h>
int main(){
const char firstname[] = "bobby";
const char* lastname = "eraserhead";
printf("%lu\n", sizeof(firstname) + sizeof(lastname));
return 0;
}
In the above code sizeof(firstname) is 6 and sizeof(lastname) is 8.
But bobby is 5 characters wide and eraserhead is 11 wide. I expect 16.
Why is sizeof behaving differently for the character array and pointer to character?
Can any one clarify?
firstname is a char array carrying a trailing 0-terminator. lastname is a pointer. On a 64bit system pointers are 8 byte wide.
sizeof an array is the size of the total array, in the case of "bobby", it's 5 characters and one trailing \0 which equals 6.
sizeof a pointer is the size of the pointer, which is normally 4 bytes in 32-bit machine and 8 bytes in 64-bit machine.
The size of your first array is the size of bobby\0. \0 is the terminator character, so it is 6.
The second size is the size of a pointer, which is 8 byte in your 64bit system. Its size doesn't depends on the assigned string's length.
how the sizeof(...) function works
sizeof() looks like a function but it's not a function. A function computes something at run-time.
sizeof() asks the compiler, at compile-time, how much memory it allocates for the argument. BTW sizeof() has no idea how much of it you actually use later at run time. In other words, you've "hardcoded" the printf arguments in your example.
Why is sizeof behaving differently for the character array and pointer
to character?
A pointer rarely requires the same amount of memory as an array.
In general, the amount of memory allocated for a pointer is different to what is allocated for its pointee.
firstname is an array of 6 chars, including the terminating '\0' character at the end of the string. That's why sizeof firstname is 6.
lastname is a pointer to char, and will have whatever size such a pointer has on your system. Typical values are 4 and 8. The size of lastname will be the same no matter what it is pointing to (or even if it is pointing to nothing at all).
firstname[] is null-terminated, which adds 1 to the length.
sizeof(lastname) is giving the size of the pointer instead of the actual value.

How sizeof works ? Memory map for variable length array of strings

const char *pointerStr[]=
{
"BEST123, ", // 0x00
"Best2233, ", // 0x01
"ABCDEFGH, ", // 0x02
"123456, ", // 0x03
"helloworld, " // 0x04
};
typedef struct
{
char value;
char name[40];
}StrInfo;
typedef struct
{
int regMax;
StrInfo info[60];
} structNew;
void main()
{
int i;
structNew pret;
for ( i=0;i<5;i++)
{
printf("PointerStr size of %dth %d \n",i,sizeof(pointerStr[i]));
printf("pret size of %dth %d \n",i,sizeof(pret.info[i].name));
}
}
The above program produce the result of
PointerStr size of 0th 4
pret size of 0th 40
PointerStr size of 1th 4
pret size of 1th 40
PointerStr size of 2th 4
pret size of 2th 40
PointerStr size of 3th 4
pret size of 3th 40
PointerStr size of 4th 4
pret size of 4th 40
If I want to know the size of each and every string in PointerStr then how to find it? Is it possible only using strlen ? do we have some other way ? How this variable length array is stored in memory ?
The result is becoz that pointerStr is pointer variable and its size is always 4. Please correct me if I am wrong.
The length of a C string is implicit: it is determined by where the terminating '\0' is in the string, so you will need a function like strlen to determine the length of a string.
The values 'returned' by sizeof are determined by the compiler by looking at the type of the data, instead of the data itself.
The reason you're getting the length of the array, but only the size of a pointer for the char*, is that sizeof is not a function call as it appears, but actually calculated at compile-time (except for variable-length arrays).
Your code exemplifies a key difference between arrays and pointers. At compile-time, the compiler knows exactly how long your array is (40), because it is statically sized. On the other hand, a char* doesn't even necessarily point to a null-terminated string, so it returns the size of the pointer.
The correct way to find the length of the strings is to use strlen. However, note that this will tell you the number of characters before the first null-byte (\0). It will not tell you how much memory is actually allocated (which is what sizeof is doing when it returns 40).
sizeof is a compiler thing. It gives the size of data, as seen during compilation. It has nothing to do with dynamic memory allocation at execution time. So sizeof(char*) or sizeof(p) with a variable declared as char* p; is often the size of the word (i.e. 4 on a 32 bits processor, 8 on a 64 bits processor) and has nothing to do with dynamic allocation, or with the actual length of the string when the program is running.
sizeof gives you the size in bytes of the variable passed to it. You are passing an array of pointers (pointing at strings) to sizeof. Arrays in C "decay" into pointers, so what you get is a pointer to the first element in your array of pointers.
And then you correctly get the size of the pointer in bytes (4 bytes = 32 bit address bus).
Because of the "array decay" rule, there is no way you can get the actual memory cell sizes of the string literals through that pointer, for the same reason that you can't get the size of an array through the pointer ptr in this example:
char array[10] = "...";
char* ptr = &array;
The solution is to either store the arrays in a different manner where you can use the sizeof on the arrays themselves (like a true 2D array), or to store all array sizes in a lookup table:
const size_t STRING_SIZES[] =
{
sizeof("BEST123, "),
sizeof("Best2233, "),
sizeof("ABCDEFGH, "),
sizeof("123456, "),
sizeof("helloworld, ")
};

Resources