Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Use sizeof(varname) instead of sizeof(type) whenever possible.
Use sizeof(varname) because it will update appropriately if the type of the variable changes. sizeof(type) may make sense in some cases, but should generally be avoided because it can fall out of sync if the variable's type changes.
sizeof(TprintPrefs) всегда, название класса. Но чаще есть typedef ClassName type; и далее используется sizeof(type)POD (for Plain Old Data) — that is a struct or class without constructors, destructors and virtual members functions.
__is_pod returns false on fundamental types.
template<typename T>
struct __IsFundamentalType { enum { result = false }; };
template<>
struct __IsFundamentalType<int> { enum { result = true }; };
template<>
struct __IsFundamentalType<char> { enum { result = true }; };
... повторить для всех фундаменталок ...
template<>
struct __IsFundamentalType<void> { enum { result = true }; };
template<typename T>
bool __is_basic(const T& var)
{
return (__IsFundamentalType<T>::result);
}
#define __is_basictype(T) (__IsFundamentalType<T>::result)
In the following example code, a float pointer *f is created as an alternative way to access the integer variable i. That is flawed code, of course, but even from experienced programmers I’ve heard the opinion that it would work nevertheless in two cases: Setting a variable to zero is deemed to be safe because on most architectures the binary representation of a floating point zero is identical to that of an integer zero.
#include <iostream> int main() { int i = 3; float *f = (float*) &i; std::cout << i << " -> "; *f = 0.; std::cout << i << std::endl; }
The naively expected output of that program would be 3 -> 0, and that’s exactly what is displayed when running an executable compiled with -O0 or -O1. However compiling with -O2 or higher, the assignment to *f is dropped because there is no subsequent read access to that variable, resulting in the output of 3 -> 3.
int i = 1;
int k = 32;
int z = i >> k;
int z = -255 >> 32;
int z = (unsigned)i >> k;
struct SomeVector2
{
float x, y;
inline SomeVector2():x(0.0f), y(0.0f){}
};
struct SomeRect
{
union{struct{float x, y;}; struct{SomeVector2 pos;};};
union{struct{float r, b;}; struct{SomeVector2 epos;};};
};
const SomeRect FullQuad = {0.0f, 0.0f, 1.0f, 1.0f};
int main(int,char*[])
{
return 0;
}
/tmp/zzz.cc:6:28: warning: 'memset' call operates on objects of type 'S' while the size is based on a different type 'S *'
[-Wsizeof-pointer-memaccess]
memset(this, 0, sizeof(this));
~~~~ ^~~~
/tmp/zzz.cc:6:28: note: did you mean to dereference the argument to 'sizeof' (and multiply it by the number of elements)?
memset(this, 0, sizeof(this));
^~~~
std::string str("20");
std::cout << str + 12;
#include <interrupt.h>
unsigned int ivar;
void bug( unsigned int val )
{
...
val = 65535U / val;
cli();
ivar = val;
sei();
...
}
sei х** знать куда, и несколько десятков тактов прерывания терялись. asm volatile("cli")" и asm volatile("sei") тоже не давала результатов.Есть компиляторы, которые ложат его в this -4(-8) байт, т.е. new «инкрементирует» this, а delete «декрементирует» this, перед тем как удалить.
А есть компиляторы, которые виртуалку не держат в объекте вообще — только в его классе
(Object *)1 - (Object *)0 равно sizeof+4(+8).int v;
memset(v, 0, sizeof(v));
AnyType v;
memset( v, 0, sizeof (&v) );
AnyType v;
memset( &v, 0, sizeof (v) );
или для указателя:AnyType * v;
memset( v, 0, sizeof (&v) );
int v[10];
memset(v, 0, sizeof(v));
Когда программист говорит, что причиной ошибки является компилятор, в 99% случаев он— начинающий программист.
#define CalcFunc(k,n) ((k*n) / (k*2 + ++n))
...
// workaround - cause of compiler bug, we save value of "x" :
long j = x;
z = CalcFunc(y, x);
x = j;
...
Во всём виноват компилятор