best cross-platform method to get aligned memory
The first function you propose would indeed work fine.
Your "homebrew" function also works, but has the drawback that if the value is already aligned, you have just wasted 15 bytes. May not matter sometimes, but the OS may well be able to provide memory that is correctly allocated without any waste (and if it needs to be aligned to 256 or 4096 bytes, you risk wasting a lot of memory by adding "alignment-1" bytes).
best cross-platform method to get aligned memory
The first function you propose would indeed work fine.
Your "homebrew" function also works, but has the drawback that if the value is already aligned, you have just wasted 15 bytes. May not matter sometimes, but the OS may well be able to provide memory that is correctly allocated without any waste (and if it needs to be aligned to 256 or 4096 bytes, you risk wasting a lot of memory by adding "alignment-1" bytes).
Best cross-platform alignment macro?
The problem is not with your clang on macOS but with the other compiler(s) allowing alignas()
(actually a macro for _Alignas()
in C)1 on the typedef
(presumably, as an extension).
From cppreference (bolding mine):
The
_Alignas
specifier can only be used when declaring objects that
aren't bit fields, and don't have the register storage class. It
cannot be used in function parameter declarations, and cannot be
used in a typedef.
Or, from this Draft C11 Standard:
6.7.5 Alignment specifier
…
Constraints
2 An alignment attribute shall not be specified in a declaration of atypedef
, or a bit-field, or a function, or a parameter, or an object declared with theregister
storage-class specifier.
1 The alignas
keyword was introduced to C++ at the C++11 Standard; ISO C11 added it as an 'alias' of the _Alignas
keyword. From the cppreference for the C++ version:
As of the ISO C11 standard, the C language has the
_Alignas
keyword
and definesalignas
as a preprocessor macro expanding to the keyword
in the header<stdalign.h>
.
How to allocate aligned memory only using the standard library?
Original answer
{
void *mem = malloc(1024+16);
void *ptr = ((char *)mem+16) & ~ 0x0F;
memset_16aligned(ptr, 0, 1024);
free(mem);
}
Fixed answer
{
void *mem = malloc(1024+15);
void *ptr = ((uintptr_t)mem+15) & ~ (uintptr_t)0x0F;
memset_16aligned(ptr, 0, 1024);
free(mem);
}
Explanation as requested
The first step is to allocate enough spare space, just in case. Since the memory must be 16-byte aligned (meaning that the leading byte address needs to be a multiple of 16), adding 16 extra bytes guarantees that we have enough space. Somewhere in the first 16 bytes, there is a 16-byte aligned pointer. (Note that malloc()
is supposed to return a pointer that is sufficiently well aligned for any purpose. However, the meaning of 'any' is primarily for things like basic types — long
, double
, long double
, long long
, and pointers to objects and pointers to functions. When you are doing more specialized things, like playing with graphics systems, they can need more stringent alignment than the rest of the system — hence questions and answers like this.)
The next step is to convert the void pointer to a char pointer; GCC notwithstanding, you are not supposed to do pointer arithmetic on void pointers (and GCC has warning options to tell you when you abuse it). Then add 16 to the start pointer. Suppose malloc()
returned you an impossibly badly aligned pointer: 0x800001. Adding the 16 gives 0x800011. Now I want to round down to the 16-byte boundary — so I want to reset the last 4 bits to 0. 0x0F has the last 4 bits set to one; therefore, ~0x0F
has all bits set to one except the last four. Anding that with 0x800011 gives 0x800010. You can iterate over the other offsets and see that the same arithmetic works.
The last step, free()
, is easy: you always, and only, return to free()
a value that one of malloc()
, calloc()
or realloc()
returned to you — anything else is a disaster. You correctly provided mem
to hold that value — thank you. The free releases it.
Finally, if you know about the internals of your system's malloc
package, you could guess that it might well return 16-byte aligned data (or it might be 8-byte aligned). If it was 16-byte aligned, then you'd not need to dink with the values. However, this is dodgy and non-portable — other malloc
packages have different minimum alignments, and therefore assuming one thing when it does something different would lead to core dumps. Within broad limits, this solution is portable.
Someone else mentioned posix_memalign()
as another way to get the aligned memory; that isn't available everywhere, but could often be implemented using this as a basis. Note that it was convenient that the alignment was a power of 2; other alignments are messier.
One more comment — this code does not check that the allocation succeeded.
Amendment
Windows Programmer pointed out that you can't do bit mask operations on pointers, and, indeed, GCC (3.4.6 and 4.3.1 tested) does complain like that. So, an amended version of the basic code — converted into a main program, follows. I've also taken the liberty of adding just 15 instead of 16, as has been pointed out. I'm using uintptr_t
since C99 has been around long enough to be accessible on most platforms. If it wasn't for the use of PRIXPTR
in the printf()
statements, it would be sufficient to #include <stdint.h>
instead of using #include <inttypes.h>
. [This code includes the fix pointed out by C.R., which was reiterating a point first made by Bill K a number of years ago, which I managed to overlook until now.]
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void memset_16aligned(void *space, char byte, size_t nbytes)
{
assert((nbytes & 0x0F) == 0);
assert(((uintptr_t)space & 0x0F) == 0);
memset(space, byte, nbytes); // Not a custom implementation of memset()
}
int main(void)
{
void *mem = malloc(1024+15);
void *ptr = (void *)(((uintptr_t)mem+15) & ~ (uintptr_t)0x0F);
printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", (uintptr_t)mem, (uintptr_t)ptr);
memset_16aligned(ptr, 0, 1024);
free(mem);
return(0);
}
And here is a marginally more generalized version, which will work for sizes which are a power of 2:
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void memset_16aligned(void *space, char byte, size_t nbytes)
{
assert((nbytes & 0x0F) == 0);
assert(((uintptr_t)space & 0x0F) == 0);
memset(space, byte, nbytes); // Not a custom implementation of memset()
}
static void test_mask(size_t align)
{
uintptr_t mask = ~(uintptr_t)(align - 1);
void *mem = malloc(1024+align-1);
void *ptr = (void *)(((uintptr_t)mem+align-1) & mask);
assert((align & (align - 1)) == 0);
printf("0x%08" PRIXPTR ", 0x%08" PRIXPTR "\n", (uintptr_t)mem, (uintptr_t)ptr);
memset_16aligned(ptr, 0, 1024);
free(mem);
}
int main(void)
{
test_mask(16);
test_mask(32);
test_mask(64);
test_mask(128);
return(0);
}
To convert test_mask()
into a general purpose allocation function, the single return value from the allocator would have to encode the release address, as several people have indicated in their answers.
Problems with interviewers
Uri commented: Maybe I am having [a] reading comprehension problem this morning, but if the interview question specifically says: "How would you allocate 1024 bytes of memory" and you clearly allocate more than that. Wouldn't that be an automatic failure from the interviewer?
My response won't fit into a 300-character comment...
It depends, I suppose. I think most people (including me) took the question to mean "How would you allocate a space in which 1024 bytes of data can be stored, and where the base address is a multiple of 16 bytes". If the interviewer really meant how can you allocate 1024 bytes (only) and have it 16-byte aligned, then the options are more limited.
- Clearly, one possibility is to allocate 1024 bytes and then give that address the 'alignment treatment'; the problem with that approach is that the actual available space is not properly determinate (the usable space is between 1008 and 1024 bytes, but there wasn't a mechanism available to specify which size), which renders it less than useful.
- Another possibility is that you are expected to write a full memory allocator and ensure that the 1024-byte block you return is appropriately aligned. If that is the case, you probably end up doing an operation fairly similar to what the proposed solution did, but you hide it inside the allocator.
However, if the interviewer expected either of those responses, I'd expect them to recognize that this solution answers a closely related question, and then to reframe their question to point the conversation in the correct direction. (Further, if the interviewer got really stroppy, then I wouldn't want the job; if the answer to an insufficiently precise requirement is shot down in flames without correction, then the interviewer is not someone for whom it is safe to work.)
The world moves on
The title of the question has changed recently. It was Solve the memory alignment in C interview question that stumped me. The revised title (How to allocate aligned memory only using the standard library?) demands a slightly revised answer — this addendum provides it.
C11 (ISO/IEC 9899:2011) added function aligned_alloc()
:
7.22.3.1 The
aligned_alloc
functionSynopsis
#include <stdlib.h>
void *aligned_alloc(size_t alignment, size_t size);
Description
Thealigned_alloc
function allocates space for an object whose alignment is
specified byalignment
, whose size is specified bysize
, and whose value is
indeterminate. The value ofalignment
shall be a valid alignment supported by the implementation and the value ofsize
shall be an integral multiple ofalignment
.Returns
Thealigned_alloc
function returns either a null pointer or a pointer to the allocated space.
And POSIX defines posix_memalign()
:
#include <stdlib.h>
int posix_memalign(void **memptr, size_t alignment, size_t size);
DESCRIPTION
The
posix_memalign()
function shall allocatesize
bytes aligned on a boundary specified byalignment
, and shall return a pointer to the allocated memory inmemptr
. The value ofalignment
shall be a power of two multiple ofsizeof(void *)
.Upon successful completion, the value pointed to by
memptr
shall be a multiple ofalignment
.If the size of the space requested is 0, the behavior is implementation-defined; the value returned in
memptr
shall be either a null pointer or a unique pointer.The
free()
function shall deallocate memory that has previously been allocated byposix_memalign()
.RETURN VALUE
Upon successful completion,
posix_memalign()
shall return zero; otherwise, an error number shall be returned to indicate the error.
Either or both of these could be used to answer the question now, but only the POSIX function was an option when the question was originally answered.
Behind the scenes, the new aligned memory function do much the same job as outlined in the question, except they have the ability to force the alignment more easily, and keep track of the start of the aligned memory internally so that the code doesn't have to deal with specially — it just frees the memory returned by the allocation function that was used.
Cross-platform ALIGN(x) macro?
I know this thread is quite old - however it is yet to be marked as answered and the solutions mentioned are not the easiest to use.
The best way to solve this is to notice that MSVC allows the declspec to appear after the declarator.
Here is my own implementation:
#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#endif
#define _ALIGNED_TYPE(t,x) typedef t ALIGNED_(x)
/*SOME USAGE SAMPLES*/
ALIGNED_TYPE_(double, 16) aligned_double_t;
ALIGNED_TYPE_(struct, CACHE_LINE) tagALIGNEDSTRUCT
{
/*STRUCT MEMBERS GO HERE*/
}aligned_struct_t;
ALIGNED_TYPE_(union, CACHE_LINE) tagALIGNEDUNION
{
/*UNION MEMBERS GO HERE*/
}aligned_union_t;
You can test this with the following code (notice the #pragma pack --> This is for MSVC)
#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#endif
#define ALIGNED_TYPE_(t,x) typedef t ALIGNED_(x)
#pragma pack(1)
typedef struct tagSTRUCTPACKED
{
int alignedInt;
double alignedDouble;
char alignedChar;
}struct_packed_t;
#pragma pack()
typedef struct tagSTRUCTNOALIGN
{
int alignedInt;
double alignedDouble;
char alignedChar;
}struct_no_align_t;
typedef struct ALIGNED_(64) tagSTRUCTALIGNED64
{
int alignedInt;
double alignedDouble;
char alignedChar;
}struct_aligned_64_t;
typedef struct tagSTRUCTWITHALIGNEDMEMBERS
{
int ALIGNED_(8) alignedInt;
double ALIGNED_(16) alignedDouble;
char ALIGNED_(2) alignedChar;
}struct_with_aligned_members_t;
int main(int argc, char **argv)
{
int i,j;
struct_packed_t _packed;
struct_no_align_t _noalign;
struct_aligned_64_t _aligned64;
struct_with_aligned_members_t _alignedmembers;
char* names[] = {"_packed","_noalign","_aligned64","_alignedmembers"};
char* ptrs[] = {(char*)&_packed,(char*)&_noalign,(char*)&_aligned64,(char*)&_alignedmembers};
size_t sizes[] = {sizeof(_packed),sizeof(_noalign),sizeof(_aligned64),sizeof(_alignedmembers)};
size_t alignments[] = {2,4,8,16,32,64};
int alcount = sizeof(alignments)/sizeof(size_t);
for(i = 0; i < 4; i++)
{
printf("Addrof %s: %x\n", names[i], ptrs[i]);
printf("Sizeof %s: %d\n", names[i], sizes[i]);
for(j = 0; j < alcount; j++)
printf("Is %s aligned on %d bytes? %s\n",
names[i],
alignments[j],
((size_t)ptrs[i])%alignments[j] == 0 ? "YES" : "NO");
}
for(j = 0; j < alcount; j++)
{
printf("Is _alignedmember.alignedInt aligned on %d bytes? %s\n",
alignments[j],
((size_t)&_alignedmembers.alignedInt)%alignments[j] == 0 ? "YES" : "NO");
printf("Is _alignedmember.alignedDouble aligned on %d bytes? %s\n",
alignments[j],
((size_t)&_alignedmembers.alignedDouble)%alignments[j] == 0 ? "YES" : "NO");
printf("Is _alignedmember.alignedChar aligned on %d bytes? %s\n",
alignments[j],
((size_t)&_alignedmembers.alignedChar)%alignments[j] == 0 ? "YES" : "NO");
}
return 0;
}
Hope this helps...
LLVM equivalent of gcc's __BIGGEST_ALIGNMENT__?
This isn't accessible from the preprocessor, but __attribute__((aligned))
or __attribute__((__aligned__))
(with the alignment value omitted) will give the alignment you want. This is supposed to give the largest alignment of any built-in type, which is 16 on x86 and ARM.
For example:
$ cat align.c
struct foo {
char c;
} __attribute__((aligned)) var;
$ clang align.c -S -o - -emit-llvm
...
@var = global %struct.foo zeroinitializer, align 16
This is used by unwind.h for _Unwind_Exception:
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
/* @@@ The IA-64 ABI says that this structure must be double-word aligned.
Taking that literally does not make much sense generically. Instead we
provide the maximum alignment required by any type for the machine. */
} __attribute__((__aligned__));
Aligned memory management?
If your implementation has a standard data type that needs 16-byte alignment (
long long
for example),malloc
already guarantees that your returned blocks will be aligned correctly. Section 7.20.3 of C99 statesThe pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object.
You have to pass back the exact same address into
free
as you were given bymalloc
. No exceptions. So yes, you need to keep the original copy.See (1) above if you already have a 16-byte-alignment-required type.
Beyond that, you may well find that your malloc
implementation gives you 16-byte-aligned addresses anyway for efficiency although it's not guaranteed by the standard. If you require it, you can always implement your own allocator.
Myself, I'd implement a malloc16
layer on top of malloc
that would use the following structure:
some padding for alignment (0-15 bytes)
size of padding (1 byte)
16-byte-aligned area
Then have your malloc16()
function call malloc
to get a block 16 bytes larger than requested, figure out where the aligned area should be, put the padding length just before that and return the address of the aligned area.
For free16
, you would simply look at the byte before the address given to get the padding length, work out the actual address of the malloc'ed block from that, and pass that to free
.
This is untested but should be a good start:
void *malloc16 (size_t s) {
unsigned char *p;
unsigned char *porig = malloc (s + 0x10); // allocate extra
if (porig == NULL) return NULL; // catch out of memory
p = (porig + 16) & (~0xf); // insert padding
*(p-1) = p - porig; // store padding size
return p;
}
void free16(void *p) {
unsigned char *porig = p; // work out original
porig = porig - *(porig-1); // by subtracting padding
free (porig); // then free that
}
The magic line in the malloc16
is p = (porig + 16) & (~0xf);
which adds 16 to the address then sets the lower 4 bits to 0, in effect bringing it back to the next lowest alignment point (the +16
guarantees it is past the actual start of the maloc'ed block).
Now, I don't claim that the code above is anything but kludgey. You would have to test it in the platforms of interest to see if it's workable. Its main advantage is that it abstracts away the ugly bit so that you never have to worry about it.
Read / write partially allocated aligned memory
See also Is it safe to read past the end of a buffer within the same page on x86 and x64? The reading part of this question is basically a duplicate of that.
It's UB according to the ISO C++ standard, but I think read-only access like this does work safely (i.e. compile to the asm that you'd expect) on implementations that provide Intel's intrinsics (which are free to define whatever extra behaviour they want). It's definitely safe in asm, but the risk is that optimizing C++ compilers that turn UB into mis-compiled code might cause a problem if they can prove that there's nothing there to read. There's some discussion of that on the linked question.
Writing outside of objects is always bad. Don't do it, not even if you put back the same garbage you read earlier: A non-atomic load/store pair can be a problem depending on what data follows your struct.
The only time this is ok is in an array where you know what comes next, and that there is unused padding. e.g. writing out an array of 3-float
structs using 16B stores overlapping by 4B. (Without alignas
for over-alignment, so an array packs them together without padding).
A struct of 3 float
s would be a much better example than 2 floats
.
For this specific example (of 2 floats) you can just use MOVSD to do a 64-bit zero-extending load, and MOVSD or MOVLPS to do a 64-bit store of the low half of an __m128
.
How to solve the 32-byte-alignment issue for AVX load/store operations?
Yes, you can use _mm256_loadu_ps
/ storeu
for unaligned loads/stores (AVX: data alignment: store crash, storeu, load, loadu doesn't). If the compiler doesn't do a bad job (cough GCC default tuning), AVX _mm256_loadu
/storeu
on data that happens to be aligned is just as fast as alignment-required load/store, so aligning data when convenient still gives you the best of both worlds for functions that normally run on aligned data but let hardware handle the rare cases where they don't. (Instead of always running extra instructions to check stuff).
Alignment is especially important for 512-bit AVX-512 vectors, like 15 to 20% speed on SKX even over large arrays where you'd expect L3 / DRAM bandwidth to be the bottleneck, vs. a few percent with AVX2 CPUs for large arrays. (It can still matter significantly with AVX2 on modern CPUs if your data is hot in L2 or especially L1d cache, especially if you can come close to maxing out 2 loads and/or 1 store per clock. Cache-line splits cost about twice the throughput resources, plus needing a line-split buffer temporarily.)
The standard allocators normally only align to alignof(max_align_t)
, which is often 16B, e.g. long double
in the x86-64 System V ABI. But in some 32-bit ABIs it's only 8B, so it's not even sufficient for dynamic allocation of aligned __m128
vectors and you'll need to go beyond simply calling new
or malloc
.
Static and automatic storage are easy: use alignas(32) float arr[N];
C++17 provides aligned new
for aligned dynamic allocation. If alignof
for a type is greater than the standard alignment, then aligned operator new
/operator delete
are used. So new __m256[N]
just works in C++17 (if compiler supports this C++17 feature; check __cpp_aligned_new
feature macro). In practice, GCC / clang / MSVC / ICX support it, ICC 2021 doesn't.
Without that C++17 feature, even stuff like std::vector<__m256>
will break, not just std::vector<int>
, unless you get lucky and it happens to be aligned by 32.
Plain-delete
compatible allocation of a float
/ int
array:
Unfortunately, auto* arr = new alignas(32) float[numSteps]
does not work for all compilers, as alignas
is applicable to a variable, a member, or a class declaration, but not as type modifier. (GCC accepts using vfloat = alignas(32) float;
, so this does give you an aligned new that's compatible with ordinary delete
on GCC).
Workarounds are either wrapping in a structure (struct alignas(32) s { float v; }; new s[numSteps];
) or passing alignment as placement parameter (new (std::align_val_t(32)) float[numSteps];
), in later case be sure to call matching aligned operator delete
.
See documentation for new
/new[]
and std::align_val_t
Other options, incompatible with new
/delete
Other options for dynamic allocation are mostly compatible with malloc
/free
, not new
/delete
:
std::aligned_alloc
: ISO C++17. major downside: size must be a multiple of alignment. This braindead requirement makes it inappropriate for allocating a 64B cache-line aligned array of an unknown number offloat
s, for example. Or especially a 2M-aligned array to take advantage of transparent hugepages.The C version of
aligned_alloc
was added in ISO C11. It's available in some but not all C++ compilers. As noted on the cppreference page, the C11 version wasn't required to fail when size isn't a multiple of alignment (it's undefined behaviour), so many implementations provided the obvious desired behaviour as an "extension". Discussion is underway to fix this, but for now I can't really recommendaligned_alloc
as a portable way to allocate arbitrary-sized arrays. In practice some implementations work fine in the UB / required-to-fail cases so it can be a good non-portable option.Also, commenters report it's unavailable in MSVC++. See best cross-platform method to get aligned memory for a viable
#ifdef
for Windows. But AFAIK there are no Windows aligned-allocation functions that produce pointers compatible with standardfree
.posix_memalign
: Part of POSIX 2001, not any ISO C or C++ standard. Clunky prototype/interface compared toaligned_alloc
. I've seen gcc generate reloads of the pointer because it wasn't sure that stores into the buffer didn't modify the pointer. (posix_memalign
is passed the address of the pointer, defeating escape analysis.) So if you use this, copy the pointer into another C++ variable that hasn't had its address passed outside the function.
#include <stdlib.h>
int posix_memalign(void **memptr, size_t alignment, size_t size); // POSIX 2001
void *aligned_alloc(size_t alignment, size_t size); // C11 (and ISO C++17)
_mm_malloc
: Available on any platform where_mm_whatever_ps
is available, but you can't pass pointers from it tofree
. On many C and C++ implementations_mm_free
andfree
are compatible, but it's not guaranteed to be portable. (And unlike the other two, it will fail at run-time, not compile time.) On MSVC on Windows,_mm_malloc
uses_aligned_malloc
, which is not compatible withfree
; it crashes in practice.Directly use system calls like
mmap
orVirtualAlloc
. Appropriate for large allocations, and the memory you get is by definition page-aligned (4k, and perhaps even 2M largepage). Not compatible withfree
; you of course have to usemunmap
orVirtualFree
which need the size as well as address. (For large allocations you usually want to hand memory back to the OS when you're done, rather than manage a free-list; glibc malloc uses mmap/munmap directly for malloc/free of blocks over a certain size threshold.)Major advantage: you don't have to deal with C++'s and C's braindead refusal provide grow/shrink facilities for aligned allocators. If you want space for another 1MiB after your allocation, you can even use Linux's
mremap(MREMAP_MAYMOVE)
to let it pick a different place in virtual address space (if needed) for the same physical pages, without having to copy anything. Or if it doesn't have to move, the TLB entries for the currently in use part stay valid.And since you're using OS system calls anyway (and know you're working with whole pages), you can use
madvise(MADV_HUGEPAGE)
to hint that transparent hugepages are preferred, or that they're not, for this range of anonymous pages. You can also use allocation hints withmmap
e.g. for the OS to prefault the zero pages, or if mapping a file on hugetlbfs, to use 2M or 1G pages. (If that kernel mechanism still works).And with
madvise(MADV_FREE)
, you can keep it mapped, but let the kernel reclaim the pages as memory pressure occurs, making it like lazilly allocated zero-backed pages if that happens. So if you do reuse it soon, you may not suffer fresh page faults. But if you don't, you're not hogging it, and when you do read it, it's like a freshly mmapped region.
alignas()
with arrays / structs
In C++11 and later: use alignas(32) float avx_array[1234]
as the first member of a struct/class member (or on a plain array directly) so static and automatic storage objects of that type will have 32B alignment. std::aligned_storage
documentation has an example of this technique to explain what std::aligned_storage
does.
This doesn't actually work until C++17 for dynamically-allocated storage (like a std::vector<my_class_with_aligned_member_array>
), see Making std::vector allocate aligned memory.
Starting in C++17, the compiler will pick aligned new
for types with alignment enforced by alignas
on the whole type or its member, also std::allocator
will pick aligned new
for such type, so nothing to worry about when creating std::vector
of such types.
And finally, the last option is so bad it's not even part of the list: allocate a larger buffer and do p+=31; p&=~31ULL
with appropriate casting. Too many drawbacks (hard to free, wastes memory) to be worth discussing, since aligned-allocation functions are available on every platform that support Intel _mm256_...
intrinsics. But there are even library functions that will help you do this, IIRC, if you insist.
Related Topics
How to Pan Images in Qgraphicsview
Comparing Two Integers Without Any Comparison
Pointers as Keys in Map C++ Stl
Dropping Privileges in C++ on Windows
What's a Good and Stable C++ Tree Implementation
How to Include Correctly -Wl,-Rpath,$Origin Linker Argument in a Makefile
How to Build Libcxx and Libcxxabi by Clang on Centos 7
How to Execute a Command and Get Return Code Stdout and Stderr of Command in C++
Converting Cv::Mat for Tesseract
Why Does Initializing an Extern Variable Inside a Function Give an Error
Pointers to Elements of Std::Vector and Std::List
Why Gcc Does Not Use Load(Without Fence) and Store+Sfence for Sequential Consistency
Visual Studio 2015 Gives Me Errors Upon Creating a Simple Test Console Program