Sizeof Taking Two Arguments

sizeof taking two arguments

In C then the array is decaying to a pointer, because of the different specification of the comma operator with relation to rvalues and lvalues (not the only place such a difference can be found). In C++ then the array stays an array, yielding the correct result.

Why call sizeof operator with two arguments?

On further research, I discovered that this is behavior specific to the WindRiver Diab compiler. Please see the EDIT in the question for details.

sizeof(T) being interpreted as two arguments

It seems you're trying to write placement new, but you're passing one argument too many. When operator new is invoked via a new expression, the first argument is always set to the size of the type being new'ed. So your code translates to a call to

operator new(size_t, size_t, T*)

The first size_t is sizeof(T) provided by the language, the second is sizeof(T) provided by your expression, and the third is the pointer.

Normal syntax for placement new is this:

new (tmp) T{std::move(buffer[i])};

What arguments does the sizeof operator take in C?

It takes a type.

sizeof(char) is always one. The variable p itself is a pointer, and on your platform that has a size of 4. Then you do &p, or a pointer to a pointer, which also has a size of 4.

On most modern desktop systems, a 32-bit architecture will have 4 byte pointers, while a 64-bit architecture will have 8 byte pointers.

sizeof itself is a keyword, resolved at compile-time, not a function. In C99, arrays can be variable length, and sizeof will wait until run-time to resolve this size.

new with multiple arguments in cppreference example

What does new(2, f) T; do?

That second argument in placement-new can be used to pass a parameter to your custom T::operator new implementation.

Here is a toy example that triggers it (in the output, you can see that the parameter f=42.0is passed to T::operator new):

#include <iostream>

struct T {
T() {
std::cout << "T::T called\n";
}

void* operator new(size_t s, int x, double f) {
std::cout << "T::new called with s=" << s << ", x=" << x << ", f=" << f << '\n';
return malloc(x * s);
}

char data[512];
};

int main() {
std::cout << "new T[5]:\n";
new T[5];

double f = 42.0;
std::cout << "\nnew(2, f) T:\n";
new(2, f) T;
}

Output:

new T[5]:
T::T called
T::T called
T::T called
T::T called
T::T called

new(2, f) T:
T::new called with s=512, x=2, f=42
T::T called

Why is sizeof() used in the argument to malloc()?

Let's look at this line of code:

int *list = malloc(3 * sizeof(int))

It creates a pointer to an int, and allocated three times the size of an int worth of memory for it. So we have enough room to store three ints in that block of memory.

I'll assume one int takes up four bytes of memory. So to store three of them, we need 12 bytes of memory (four bytes per int times three ints). malloc allocates space in bytes, so that will give you 12 bytes of memory (sizeof(int) will return four as there are four bytes per int*).

Now let's look at the other version:

int *list = malloc(3)

You allocate three bytes of memory. Sadly, one int is four bytes... so you have enough space for 3/4 of an int (again, assuming one int is four bytes). If you wanted to store three ints, you need to allocate memory equal to three times however big an int is, hence 3 * sizeof(int).


*Technically, there are platforms where an int isn't four bytes. So it is better to write sizeof(int) instead of 4. Don't worry about that for now, though.

Significance of two arguments in fread?

There is a behavior difference if there is not enough data to satisfy the request. From the page you linked to:

The total number of elements successfully read are returned as a size_t object, which is an integral data type. If this number differs from the nmemb parameter, then either an error had occurred or the End Of File was reached.

So if you specify that there is only one element of size sizeof(arr), and there is not enough data to fill arr, then you won't get any data returned. If you do:

fread(arr, sizeof(int), sizeof(arr) / sizeof(int), fp);

then arr will be partially filled if there is not enough data.

The third line of your code most naturally fits the API of fread. However, you could use one of the other forms if you document why you are not doing the normal thing.

Why in C does the function sizeof() output the size of right most operand when more than one operands are passed separated by comma?

The simple reason is: Because sizeof is not a function! It is an operator that takes some expression on its right. Syntactically, it behaves the same as the return operator. The parentheses are only added by the programmers for clarity, and are not needed in most cases:

sizeof(foo);       //no surprise, take the size of the variable/object
sizeof foo; //same as above, the parentheses are not needed

sizeof(void*); //you cannot pass a type to a function, but you can pass it to the sizeof operator
sizeof void*; //same as above

typedef char arrayType[20]
arrayType* bar; //pointer to an array
sizeof(*bar); //you cannot pass an array to a function, but you can pass it to the sizeof operator
sizeof*bar; //same as above

//compare to the behavior of `return`:
return foo; //no surprise
return(foo); //same as above, any expression may be enclosed in parentheses

So, what happens when you say sizeof(5, 5.0)? Well, since sizeof is an operator, the parentheses are not a function call, but rather interpreted like the parentheses in 1*(2 + 3) == 5. In both cases, the ( follows an operator, and is thus not interpreted as a function call. As such, the comma does not separate function call arguments (because there is no function call), rather it's interpreted as the comma operator. And the comma operator is defined to evaluate both its operands, and then return the value of the last operand. The operator nature of the sizeof dictates how the expression on its right is parsed.



Related Topics



Leave a reply



Submit