LINUX.ORG.RU
Ответ на: комментарий от Dudraug

В последнем варианте наверное будет более корректно использовать decltype вместо sizeof. Но так как вопрос все равно о си, то юзай первый вариант или что-то в этом роде.

Dudraug ★★★★ ()
Последнее исправление: Dudraug (всего исправлений: 1)
Ответ на: комментарий от Dudraug

Ну да, пожалуй.

Да ну, хипстерство... Если уж так нужно узнать, то нехай развертывает до стандартных типов, а когда получится ровно то, что в примере топика, то есть long, то уж sizeof этого то узнать можно многими способами.

Если кому интересно, то кроскомпиляторный метод определения размера типа заключается в попытке скомпилить: switch(sizeof(TYPE)) { case 4: break; case sizeof(TYPE): break; } Как ругнётся, значить угадали :))

vodz ★★ ()
Ответ на: комментарий от DELIRIUM

изобретает sizeof?

Кстати, интересная тема: изобрести sizeof. У меня получилось так:

#include <stdio.h>

struct st {
	long fld1;
};

#define sizeof_field(type, field) \
    ((size_t)((char *)(&((type *)0)->field + 1) - (char *)&((type *)0)->field))

const size_t sz = sizeof_field(struct st, fld1);

int main(void) {
	printf("%zu\n", sz);
}

Интересно, что здесь может пойти не так.

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

Интересно, что здесь может пойти не так.

6.5.3.2 (Address and indirection operators), параграф 4

The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.(сноска)

В сноске написано:
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.

utf8nowhere ()
Ответ на: комментарий от i-rinat

Ок, я исходил из того, что в C, как и в C++, E1->E2 эквивалентно (*E1).E2 (для встроенного оператора ->), но это не так. В C поведение -> описывается без опоры на оператор *. Но всё равно тут UB. См. https://software.intel.com/en-us/blogs/2015/04/20/null-pointer-dereferencing-...

utf8nowhere ()
Ответ на: комментарий от utf8nowhere

Да, действительно, вне функции тоже можно. Но формально будет создаваться глобальный безымянный объект, к которому никто уже обратиться не сможет.

Sorcerer ★★★★★ ()
Ответ на: комментарий от utf8nowhere

The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

По факту оптимизатор может и не будет создавать объект, но конструкция с кастом NULL к указателю на структуру как-то надежней выглядит.

Sorcerer ★★★★★ ()
Последнее исправление: Sorcerer (всего исправлений: 1)
Ответ на: комментарий от Sorcerer

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.

utf8nowhere ()