Is it OK to use both parts of a union if you know the parts don't overlap? Like in this example, is it OK to use both buf[31] as well as ps?
struct PtrSize {
const char *data;
size_t size;
};
class SmallStringOrNot {
union {
PtrSize ps;
char buf[32];
} pb;
public:
bool IsSmallString() const {
return pb.buf[31] != 0;
}
SmallStringOrNot(const char *str) {
size_t len = strlen(str);
if (len && len < 31) {
memcpy(pb.buf, str, len);
pb.buf[31] = len;
} else {
pb.ps.data = str;
pb.ps.size = len;
pb.buf[31] = 0; // is this OK, accessing buf right after ps?
}
}
PtrSize AsPtrSize() const {
if (IsSmallString()) {
return PtrSize{pb.buf, pb.buf[31]};
} else {
return pb.ps;
}
}
};
Unfortunately the code is not OK: you are at least not in "undefined behaviour"-zone, since in C++ it is always legal to access a union through a char member, but you have no guarantee that by modifying buf[31] you are not altering ps.data or ps.size. In a 128-bit machine you would almost surely be doing it.
On more normal architectures, your code should be fine but for a 100% guarantee you should refer to the compiler documentation, since size_t could in principle be bigger than a void*. For example, even on a 64-bit machine you could theoretically have a 192-bit ps.size member (which summed with the 64 bit of the ps.data pointer would make the PtrSize completely overlap the buffer.
Related
I'm wondering if it's possible to hint to gcc that a pointer points to an aligned boundary. if I have a function:
void foo ( void * pBuf ) {
uint64_t *pAligned = pBuf;
pAligned = ((pBuf + 7) & ~0x7);
var = *pAligned; // I want this to be aligned 64 bit access
}
And I know that pBuf is 64 bit aligned, is there any way to tell gcc that pAligned points to a 64 bit boundary? If I do:
uint64_t *pAligned __attribute__((aligned(16)));
I believe that means that the address of the pointer is 64 bit aligned, but it doesn't tell the compiler that the what it points to is aligned, and therefore the compiler would likely tell it to do an unaligned fetch here. This could slow things down if I'm looping through a large array.
There are several ways to inform GCC about alignment.
Firstly you can attach align attribute to pointee, rather than pointer:
int foo() {
int __attribute__((aligned(16))) *p;
return (unsigned long long)p & 3;
}
Or you can use (relatively new) builtin:
int bar(int *p) {
int *pa = __builtin_assume_aligned(p, 16);
return (unsigned long long)pa & 3;
}
Both variants optimize to return 0 due to alignment.
Unfortunately the following does not seem to work:
typedef int __attribute__((aligned(16))) *aligned_ptr;
int baz(aligned_ptr p) {
return (unsigned long long)p & 3;
}
and this one does not either
typedef int aligned_int __attribute__((aligned (16)));
int braz(aligned_int *p) {
return (unsigned long long)p & 3;
}
even though docs suggest the opposite.
I am trying to use recursion to solve this problem where if i call
decimal<0,0,1>();
i should get the decimal number (4 in this case).
I am trying to use recursion with variadic templates but cannot get it to work.
Here's my code;
template<>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a*2 + decimal<pack...>();
};
int main(int argc, char *argv[]){
cout<<decimal<0,0,1>()<<endl;
return 0;
}
What would be the best way to solve this?
template<typename = void>
int decimal(){
return 0;
}
template<bool a,bool...pack>
int decimal(){
cout<<a<<"called"<<endl;
return a + 2*decimal<pack...>();
};
The problem was with the recursive case, where it expects to be able to call decltype<>(). That is what I have defined in the first overload above. You can essentially ignore the typename=void, the is just necessary to allow the first one to compile.
A possible solution can be the use of a constexpr function (so you can use it's values it's value run-time, when appropriate) where the values are argument of the function.
Something like
#include <iostream>
constexpr int decimal ()
{ return 0; }
template <typename T, typename ... packT>
constexpr int decimal (T const & a, packT ... pack)
{ return a*2 + decimal(pack...); }
int main(int argc, char *argv[])
{
constexpr int val { decimal(0, 0, 1) };
static_assert( val == 2, "!");
std::cout << val << std::endl;
return 0;
}
But I obtain 2, not 4.
Are you sure that your code should return 4?
-- EDIT --
As pointed by aschepler, my example decimal() template function return "eturns twice the sum of its arguments, which is not" what do you want.
Well, with 0, 1, true and false you obtain the same; with other number, you obtain different results.
But you can modify decimal() as follows
template <typename ... packT>
constexpr int decimal (bool a, packT ... pack)
{ return a*2 + decimal(pack...); }
to avoid this problem.
This is a C++14 solution. It is mostly C++11, except for std::integral_sequence nad std::index_sequence, both of which are relatively easy to implement in C++11.
template<bool...bs>
using bools = std::integer_sequence<bool, bs...>;
template<std::uint64_t x>
using uint64 = std::integral_constant< std::uint64_t, x >;
template<std::size_t N>
constexpr uint64< ((std::uint64_t)1) << (std::uint64_t)N > bit{};
template<std::uint64_t... xs>
struct or_bits : uint64<0> {};
template<std::int64_t x0, std::int64_t... xs>
struct or_bits<x0, xs...> : uint64<x0 | or_bits<xs...>{} > {};
template<bool...bs, std::size_t...Is>
constexpr
uint64<
or_bits<
uint64<
bs?bit<Is>:std::uint64_t(0)
>{}...
>{}
>
from_binary( bools<bs...> bits, std::index_sequence<Is...> ) {
(void)bits; // suppress warning
return {};
}
template<bool...bs>
constexpr
auto from_binary( bools<bs...> bits={} )
-> decltype( from_binary( bits, std::make_index_sequence<sizeof...(bs)>{} ) )
{ return {}; }
It generates the resulting value as a type with a constexpr conversion to scalar. This is slightly more powerful than a constexpr function in its "compile-time-ness".
It assumes that the first bit is the most significant bit in the list.
You can use from_binary<1,0,1>() or from_binary( bools<1,0,1>{} ).
Live example.
This particular style of type-based programming results in code that does all of its work in its signature. The bodies consist of return {};.
I'm using gcc 5.1.0 (c++14) and I was trying with constexpr. Is very annoying to verify if the constexpr I've implemented are evaluated at compile time. I couldn't find any flag for get a warning about that situation.
Here is an example:
example.cpp -----------------------------------------
#include <stdlib.h>
const char pruVar[] = "12345678901234567";
[[gnu::noinline]] constexpr unsigned int myStrlen(const char* cstr)
{
unsigned int i=0;
for(;cstr[i]!=0;++i);
return i;
}
struct CEXAMPLE
{
unsigned int size;
constexpr CEXAMPLE(const char* s): size(myStrlen(s))
{
}
};
int main(void)
{
CEXAMPLE c(pruVar);
unsigned int size = myStrlen(pruVar);
void* a = malloc(c.size + size);
if (a != nullptr)
return 0;
else
return 1;
}
In the example CEXAMPLE::CEXAMPLE is evaluated at compile time including the call to myStrlen in it, but the call to myStrlen in main is being evaluated at runtime. The only way I have to know this is looking at the assembler.This website is very useful too: http://gcc.godbolt.org/
If you know how to make the compiler warn about this or something similar I'll appreciate it
myStrlen(pruVar) can be evaluated at compile time; the compiler is just choosing not to in this instance.
If you want to force the compiler to evaluate it at compile time or error if this is not possible, assign the result to a constexpr variable:
constexpr unsigned int size = myStrlen(pruVar);
^^^^^^^^^
You could also use an enum, or a std::integral_constant:
enum : unsigned int { size = myStrlen(pruVar) };
std::integral_constant<unsigned int, myStrlen(pruVar)> size;
Based on the fact that template arguments must be evaluated at compiletime a helper template can be used.
namespace helper {
template<class T, T v> constexpr T enforce_compiletime() {
constexpr T cv = v;
return cv;
}
}
#define compiletime(arg) ::helper::enforce_compiletime<decltype(arg), (arg)>()
This allows compile time enforcement without an additional constexpr variable, which is handy in order to calculate value lookup tables.
constexpr uint32_t bla(uint8_t blub) {
switch (blub) {
case 5:
return 22;
default:
return 23;
}
}
struct SomeStruct {
uint32_t a;
uint32_t b;
};
SomeStruct aStruct = {compiletime(bla(5)), compiletime(bla(6))};
following is code of function
void printf(char *ch,void *num,...)
{
int i;
va_list ptr; //to store variable length argument list
va_start(ptr,num); // initialise ptr
for(i=0;ch[i]!='\0';i++)
{
if(ch[i]=='%') // check for % sign in print statement
{ i++;
if( ch[i]=='d')
{
int *no = (int *)va_arg(ptr,int * );
int value=*no; // just used for nothing
printno(value); //print int number
}
if( ch[i]=='u')
{
unsigned long *no =(unsigned long *) va_arg(ptr,unsigned long *);
unsigned long value=*no;
printuno(value); //print unsigned long
}
}
else // if not % sign then its regular character so print it
{
printchar(ch[i]);
}
}
}
this my code for printf() to print integer value and uint values
It is working fine for string portion in arguments but for %d %u it shows the same
values for all variables. This value is 405067 - even though the values of the variables are different.
Please tell me how to fix this.
Why are you interpreting the argument as a pointer? I'm surprised you aren't crashing. You should just be using
int num = va_arg(ptr,int);
printno(num);
and
unsigned int num = va_arg(ptr,unsigned int);
printuno(value);
(note, unsigned int, not unsigned long, because that would actually be %lu)
Also, get rid of the num parameter. It's wrong. Your va_list should be initialized as
`va_start(ptr, ch);`
va_start() takes the last argument before the varargs, not the first argument.
As noted in a comment, the C99 prototype for printf() is:
int printf(const char * restrict format, ...);
Therefore, if you're calling your function printf(), you should probably follow its design. I'm going to ignore flags, field width, precision and length modifiers, assuming that the conversion specifiers are simply two characters each, such as %d or %%.
int printf(const char * restrict format, ...)
{
va_list args;
va_start(args, format);
char c;
int len = 0;
while ((c = *format++) != '\0')
{
if (c != '%')
{
putchar(c);
len++;
}
else if ((c = *format++) == '%')
{
putchar(c);
len++;
}
else if (c == 'd')
{
int value = va_arg(args, int);
len += printno(value);
}
else if (c == 'u')
{
unsigned value = va_arg(args, unsigned);
len += printuno(value);
}
else
{
/* Print unrecognized formats verbatim */
putchar('%');
putchar(c);
len += 2;
}
}
return len;
}
Dealing with the full set of format specifiers (especially if you add the POSIX n$ notation as well as flags, field width, precision and length modifiers) is much harder, but this should get you moving in the correct direction. Note that I assume the printno() and printuno() functions both report how many characters were written for the conversion specifier. The function returns the total number of characters written. Note, too, that production code would need to allow for the called functions to fail, and would therefore probably not use the len += printno(value); notation, but would capture the return from printno() into a separate variable that could be tested for an error before adding it to the total length output.
Is there efficient way to do this?
That's something you could be using a union for:
union {
UINT64 ui64;
struct {
DWORD d0;
DWORD d1;
} y;
} un;
un.ui64 = 27;
// Use un.y.d0 and un.y.d1
An example (under Linix so using different types):
#include <stdio.h>
union {
long ui64;
struct {
int d0;
int d1;
} y;
} un;
int main (void) {
un.ui64 = 27;
printf ("%d %d\n", un.y.d0, un.y.d1);
return 0;
}
This produces:
27 0
Thought I would provide an example using LARGE_INTEGER FOR the windows platform.
If I have a variable called "value" that is 64 bit, then I do:
LARGE_INTEGER li;
li.QuadPart = value;
DWORD low = li.LowPart;
DWORD high = li.HighPart;
Yes, this copies it, but I like the readability of it.
Keep in mind that 64-bit integers have alignment restrictions at least as great as 32-bit integers on all platforms. Therefore, it's perfectly safe to cast a pointer to a 64-bit integer as a pointer to a 32-bit.
ULONGLONG largeInt;
printf( "%u %u\n", ((DWORD *)&largeInt)[ 0 ], ((DWORD *)&largeInt)[ 1 ] );
Obviously, Pax's solution is a lot cleaner, but this is technically more efficient since it doesn't require any data copying.