Solving C++ 'target of assignment not really an lvalue' errors - c++

Given this code:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
while (sz8-- != 0) {
*((double *)to)++ = *((double *)from)++;
}
while (sz1-- != 0) {
*((char *)to)++ = *((char *)from)++;
}
}
I am receiving target of assignment not really an lvalue warnings on the 2 lines inside the while loops.
Can anyone break down those lines?
a cast then an increment?
What is a simplier way to write that?
What does the error mean?

It does not like the *((char*)to)++ statement.
Try this:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double * tod = (double *) to;
double * fromd = (double *) from;
while (sz8-- != 0) {
*(tod++) = *(fromd++);
}
char * toc = (char *) tod;
char * fromc = (char *) fromd;
while (sz1-- != 0) {
*(toc++) = *(fromc++);
}
}

You can't apply ++ to the result of a cast, only to an lvalue (a variable). So you need to create new variable with the appropriate types for the increments:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double *to1 = (double *)to;
double *from1 = (double *)from
while (sz8-- != 0) {
*to1++ = *from1++;
}
char *to2 = (char *)to1;
char *from2 = (char *)from1;
while (sz1-- != 0) {
*to2++ = *from2++;
}
}

I tried to rewrite it in a way that no warning appears:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
double *xto = (double *)to;
double *xfrom = (double *)from;
while (sz8-- != 0) {
*xto++ = *xfrom++;
}
char *cto = (char *)to;
char *cfrom = (char *)from;
while (sz1-- != 0) {
*cto++ = *cfrom++;
}
}

The result of explicit type conversion is rvalue in this case - according to 5.4.1 of C++11 Standard. You cannot apply increment operator to rvalue, it shall be lvalue. See C++ value category for details.
Use temporary variables to obtain required effect:
double* to_dbl = static_cast<double*>(to);
double* from_dbl = static_cast<double*>(from);
while(sz8-- != 0)
{
*(to_dbl++) = *(from_dbl++);
}

You are performing an increment operation on the LValue (Left side value of the assignment operator). Logically and by definition, a LValue must always be a variable. It cannot be a constant. When you are performing an increment operation, it is leaving a constant value on the Left Side which is giving you the error.

First before answering let me just say: Don't try to out-micro-optimize your compiler/library. The compiler writers will win something like 99 times out of 100. Use std::copy or memcpy depending on the types you're copying and needs.
Other answers have noted that you can solve the immediate compilation errors with temporary variables.
I don't recommend this under any circumstances do the following, but I believe you can also accomplish this by casting to a reference type:
void FrMemCopy(void *to, const void *from, size_t sz)
{
size_t sz8 = sz >> 3;
size_t sz1 = sz - (sz8 << 3);
while (sz8-- != 0) {
*((double *&)to)++ = *((double *&)from)++;
}
while (sz1-- != 0) {
*((char *&)to)++ = *((char *&)from)++;
}
}

Related

Can I cast void * to ptrdiff_t in C89?

Will the C89 standard allow me to cast void * to ptrdiff_t so I can print the memory location as hexadecimal?
For example:
static const char *dig = "0123456789abcdef";
char buf[16], *ptr = buf; /* Need 16 bytes when sizeof(void *) == 8 */
void *val;
ptrdiff_t tmp = (const unsigned char *) val - (const unsigned char *) 0;
do {
*buf++ = dig[tmp & 0xf];
tmp >>= 4;
} while (tmp);
do {
putc(*--ptr);
} while (ptr > buf);
Context: I am writing a printf() function in kernel space.

C++ Dynamic array has not requested size

While creating a custom class for STL Multimap, I came across an unintended behaviour where dynamic arrays created by new operator are not of the size between []. In the following code, in a.Set(3, 'c') the arrays stored in newKey and newSize are of size one, when they should have size two. Using the debugger shows that in that lines index is equal to 1, so size should be two. Program does not produce any exception but it also does not output the expected result c.
As clarification, using the debugger shows that the problem occurs while setting the value at index 1 in newKey, newSize, newValue. It does not throw any kind of exception, but does not change any value either.
template<typename T>
void Copy(T const* _source, T* _destiny, unsigned long _size)
{
for (unsigned long i = 0; i < _size; i++)
{
_destiny[i] = _source[i];
}
}
template<typename T>
void CopyNew(T const* _source, T* _destiny, unsigned long _size)
{
T* target = new T[_size];
for (unsigned long i = 0; i < _size; i++)
{
target[i] = _source[i];
}
_destiny = target;
}
template<typename T1, typename T2>
class Multimap
{
public:
Multimap() {}
unsigned long Get(T1 const& _key, T2** _return)
{
for (unsigned long i = 0; i < this->keySize_; i++)
{
if (_key == this->key_[i])
{
CopyNew<T2>(this->value_[i], *_return, this->valueSize_[i]);
return i;
}
}
*_return = 0;
return this->keySize_;
}
unsigned long Get(T1 const& _key)
{
for (unsigned long i = 0; i < this->keySize_; i++)
{
if (_key == this->key_[i])
{
return i;
}
}
return this->keySize_;
}
int Set(T1 const& _key, T2 const& _value)
{
T2* target;
unsigned long index = this->Get(_key, &target);
if (target == 0)
{
T1* newKey = new T1[index + 1];
unsigned long* newSize = new unsigned long[index + 1];
T2** newValue = new T2*[this->keySize_ + 1];
if (this->keySize_ != 0)
{
Copy(this->key_, newKey, index);
delete[] this->key_;
Copy(this->valueSize_, newSize, index);
for (unsigned long i = 0; i < this->keySize_; i++)
{
newValue[i] = new T2[this->valueSize_[i]];
Copy(this->value_[i], newValue[i], this->valueSize_[i]);
delete[] this->value_[i];
}
delete[] this->valueSize_;
}
newKey[index] = _key;
newSize[index] = 0;
this->key_ = newKey;
this->valueSize_ = newSize;
this->value_ = newValue;
this->keySize_++;
}
unsigned long newSize = this->valueSize_[index]+1;
T2* newValue = new T2[newSize];
Copy(this->value_[index], newValue, newSize-1);
newValue[newSize-1] = _value;
this->valueSize_[index] = newSize;
this->value_[index] = newValue;
return newSize;
}
unsigned int GetSize()
{
return this->keySize_;
}
protected:
unsigned long keySize_ = 0;
unsigned long* valueSize_ = 0;
T1* key_ = 0;
T2** value_ = 0;
};
int main()
{
Multimap<int, char> a;
a.Set(2, 'b');
a.Set(3, 'c');
char* b;
a.Get(3, &b);
std::cout << b[0];
}
CopyNew argument _destiny should be T*& (as pointed out by WhozCraig in the comments). Otherwise, the function is changing the argument but not the variable passed to the function. In order to change the variable, you have to de-reference the argument, so its type has to be either a pointer or a reference to the variable type. Since the type of the variable is T*, the argument type should be T** or T*&

atomicCAS for bool implementation

I'm trying to figure out is there a bug in the answer (now deleted) about the implementation of Cuda-like atomicCAS for bools. The code from the answer (reformatted):
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 7; // byte position within the unsigned long long
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
do
{
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return (bool)(old & ((0xFFU) << (8 * pos)));
}
According to the documentation, atomicCAS should set *address to (*address == compare ? val : *address), but in the implementation above compare argument is never used!
The code I use to reproduce the bug:
#include <cstdio>
// atomicCAS definition here
__device__ bool b;
__global__ void kernel()
{
b = false;
atomicCAS(&b, true, true); // `(b == true ? true : b)`, where b is false equals to false
printf("%d\n", b); // b is false => expected output is 0
}
int main()
{
kernel<<<1, 1>>>();
cudaDeviceSynchronize();
}
The expected output is 0, but the actual output is 1.
I have a suggestion about how to fix it but am not 100% sure it's thread-safe:
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
do
{
if(*address != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return (bool)(old & ((0xFFU) << (8 * pos)));
}
My questions are
Is there a bug in the first code sample from the answer? If there is,
Does the last code sample fix it thread-safely?
Many many thanks to #RobertCrovella; the first code sample does contain a bug, the second does fix it, but is not thread-safe (see question comments for details). The thread-safe fix:
static __inline__ __device__ bool atomicCAS(bool *address, bool compare, bool val)
{
unsigned long long addr = (unsigned long long)address;
unsigned pos = addr & 3; // byte position within the int
int *int_addr = (int *)(addr - pos); // int-aligned address
int old = *int_addr, assumed, ival;
bool current_value;
do
{
current_value = (bool)(old & ((0xFFU) << (8 * pos)));
if(current_value != compare) // If we expected that bool to be different, then
break; // stop trying to update it and just return it's current value
assumed = old;
if(val)
ival = old | (1 << (8 * pos));
else
ival = old & (~((0xFFU) << (8 * pos)));
old = atomicCAS(int_addr, assumed, ival);
} while(assumed != old);
return current_value;
}

c++ template method syntax issue

I am trying to create a method that creates an array of double the size given, then fills the first half of the array with the original values and the second half with the original values in reverse order. I have completed this but the next task is to make the method accept arrays of generic type and i'm stuck and not sure where to go from here
my code so far:
template <typename T>
T& *copy_and_reverse(T& *a, int length) {
T& *result = new T&[length*2];
int w = length-1;
for (int i = 0; i < length * 2; i++) {
if (i < length) {
result[i] = a[i];
} else {
result[i]=a[w];
w--;
}
}
return result;
}
int main() {
double numbers[5]={8.364,4.3,5.3,9.6,7.645};
int size=sizeof numbers/sizeof(double);
double *pointertonumbers;
pointertonumbers=copy_and_reverse(numbers, size);
for(int i=0;i<size*2;i++){
cout<<pointertonumbers[i]<<"\n";
}
}
at the moment the code does not work as i get multiple "error: cannot declare pointer to 'T&'"
If the compilre says that it cannot declare pointer to T& then try to declare a reference to T *. Maybe the compiler will be happy in this case.:)
T * copy_and_reverse( const T *a, int length) {
T *result = new T[length*2];
As for me I would use standard algorithm std::copy. For example
template <typename T>
T * copy_and_reverse( const T *a, size_t length)
{
T *result = new T[ 2 * length ];
std::copy( a, a + length, result );
std::copy( a, a + length, reverse_iterator<int *>( result + 2 * length ) );
return result;
}
First, you cannot create pointer to reference (what you are trying to do). Reference to a pointer would be T* &a. And you should not return pointer to a reference (and reference to a pointer either, as it will create dangling reference)
Actually, it's better to be on a safe side and accept a reference to an array.
T* copy_and_reverse(T (&a) [N]) {
T *result = new T[N*2];
size_t w = N-1;
for (size_t i = 0; i < N * 2; i++) {
if (i < N) {
result[i] = a[i];
} else {
result[i]=a[w];
w--;
}
}
return result;
}
int main() {
double numbers[5]={8.364,4.3,5.3,9.6,7.645};
int size=sizeof numbers/sizeof(double);
double *pointertonumbers;
pointertonumbers=copy_and_reverse(numbers);
for(int i=0;i<size*2;i++){
std::cout<<pointertonumbers[i]<<"\n";
}
delete [] pointertonumbers;
}
This still have issues. You should not forget to delete result of a function. With C++11 you can rewrite it really safe with std::arrays:
std::array<T, N*2> copy_and_reverse(const std::array<T, N>& orig) {
std::array<T, N*2> result;
std::copy(orig.begin(), orig.end(), result.begin());
std::copy(orig.begin(), orig.end(), std::reverse_iterator<typename std::array<T, N*2>::iterator>(result.end()));
return std::move(result);
}
int main() {
std::array<double, 5> numbers = {{8.364,4.3,5.3,9.6,7.645}};
auto pointertonumbers(copy_and_reverse(numbers));
for(size_t i=0;i<pointertonumbers.size();i++){
std::cout<<pointertonumbers[i]<<"\n";
}
}
Here you get rid of pointers (and all its issues) completely.

C++ vector equivalent in C [duplicate]

This question already has answers here:
How to replicate vector in c?
(6 answers)
Closed 2 years ago.
I have a code (C++) that looks like this
vector<int> values[10000];
int i, j;
while (.....) {
scanf("%d%d", &i, &j);
values[i].push_back(j);
values[j].push_back(i);
}
but I want to rewrite this code to C. How can I do this?
I researched the opportunity to make the own stack, but maybe have more lightweight way to rewrite this code, maybe two-dimensional arrays. So far I can not think how this remake, I hope that someone more experienced tell me how to do it :)
Sorry guys, added a more advanced example...
Instead of rolling your own, you may want to try a C container library, e.g. http://code.google.com/p/ccl/
You can use Gena library. It closely resembles stl::vector in pure C89.
You can check it out here:
https://github.com/cher-nov/Gena
Something like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct _darray
{
size_t size;
size_t actual_size;
int *content;
} darray;
void darray_create(darray *d)
{
d->actual_size = d->size = 0;
d->content = NULL;
}
void darray_append(darray *d, int v)
{
if (d->size+1 > d->actual_size)
{
size_t new_size;
if (!d->actual_size)
{
new_size = 1;
}
else
{
new_size = d->actual_size * 2;
}
int *temp = realloc(d->content, sizeof(int) * new_size);
if (!temp)
{
fprintf(stderr, "Failed to extend array (new_size=%zu)\n", new_size);
exit(EXIT_FAILURE);
}
d->actual_size = new_size;
d->content = temp;
}
d->content[d->size] = v;
d->size++;
}
const int* darray_data(darray *d)
{
return d->content;
}
void darray_destroy(darray *d)
{
free(d->content);
d->content = NULL;
d->size = d->actual_size = 0;
}
size_t darray_size(darray *d)
{
return d->size;
}
int main()
{
int i;
darray myarray;
const int *a;
darray_create(&myarray);
for(i = 0; i < 100; i++)
{
darray_append(&myarray, i);
}
a = darray_data(&myarray);
for(i = 0; i < darray_size(&myarray); i++)
{
printf("i=%d, value=%d\n", i, a[i]);
}
darray_destroy(&myarray);
}
You can try something like this:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct vector
{
int len;
int allocated;
int step;
int *data;
};
#define INIT_SIZE 1
void init_vector(struct vector *v)
{
v->len = 0;
v->allocated = 0;
v->step = 2;
v->data = NULL;
}
int append(struct vector *v, int item)
{
if (!v->data)
{
v->data = malloc(INIT_SIZE * sizeof(int));
if (!v->data)
return -1;
v->allocated = INIT_SIZE;
}
else
if (v->len >= v-vallocated)
{
int *tmp = realloc(v->data,
v->allocated * v->step * sizeof(int));
if (!tmp)
return -1;
v->data = tmp;
v->allocated *= v->step;
}
v->data[v->len] = item;
v->len++;
return 0;
}
int delete(struct vector *v, int index)
{
if (index < 0 || index >= v->len)
return -1;
memmove(v->data + index, v->data + index + 1,
(v->len - index - 1) * sizeof(int));
v->len--;
return 0;
}
void print(const struct vector *v)
{
printf("Array:\n");
for (int i = 0; i < v->len; i++)
printf("%d ", v->data[i]);
printf("\n");
}
int main(void)
{
struct vector v;
int rc;
init_vector(&v);
rc = append(&v, 1);
assert(rc == 0);
rc = append(&v, 2);
assert(rc == 0);
rc = append(&v, 3);
assert(rc == 0);
rc = append(&v, 4);
assert(rc == 0);
rc = append(&v, 5);
assert(rc == 0);
print(&v);
rc = delete(&v, 2);
assert(rc == 0);
print(&v);
free(v.data);
return 0;
}
A rough equivalent of a C++ vector would be a resizing C array (to account for more elements than available).
Ergo, the equivalent of an array of vectors would be an array of pointers (an array of arrays wouldn't cut it because of the resizing constraint).
int* values[1000];
You'll need to account for the sizes though, so you could either do that externally or wrap the logic inside a structure.
int sizes[1000];
int noElements[1000];
// all sizes and noElements initially 0
for (int i = 0; i < 10; i++) {
if ( noElements[i] >= sizes[i] )
{
// allocate more memory for values[i];
// copy old contents into the new memory
// update sizes[i]
}
values[i][noElements] = 10;
noElements++;
}
There is no C standard equivalent to the c++ vector, though you could create a struct based off of the vector in c++. The struct would
Resize itself if the array bounds are passed the max size
perform the operations similar to that of a vector
OR
Create a linked list stack struct that simulates that of a c++ vector
I'm affraid you'll have to work with heap memory in 80's fashion in the plain C.
typedef struct tagArrayDesc {
int* arr;
size_t top;
size_t reserved;
} ArrayDesc;
#define EC(NAME, T) size_t ensure_capacity##NAME##(size_t size, \
T** vec, \
size_t reserved) \
{ \
size_t new_reserved; \
new_reserved = reserved; \
if (reserved < size) { \
if (reserved != 0) { \
new_reserved *= 2; \
} else { \
new_reserved = 0x10; \
} \
} \
if (new_reserved < size) { \
new_reserved = (size * 4) / 3; \
} \
if (new_reserved > reserved) { \
*vec = realloc(*vec, sizeof(**vec) * new_reserved); \
memset((*vec) + reserved, 0, sizeof(T) * (new_reserved - reserved)); \
} \
return new_reserved; \
}
EC(_int, int)
EC(_array_desc, ArrayDesc)
int main()
{
ArrayDesc* rows = NULL;
size_t rows_size = 0;
size_t rows_reserved = 0;
while (true) {
int i, j;
scanf("%d%d", &i, &j);
rows_reserved = ensure_capacity_array_desc(i + 1, &rows, rows_reserved);
rows[i].reserved = ensure_capacity_int(j + 1, &rows[i].arr, rows[i].reserved);
rows[i].arr[j] = 42;
}
return 0;
}
You have to work with dynamic memory allocation. It's not hard. Every time when a new item must be inserted just use realloc. Somethink that looks like this:
#include <cstdlib>
typedef struct { } UserType;
int currentSize = 0;
UserType* values;
/// Add new value to values method
void addValue(const UserType& newValue)
{
++currentSize;
values = static_cast<UserType*>(realloc(values, currentSize));
if (values == NULL)
// memory allocation filed, place fix code here
*(values + currentSize) = newValue;
}
Remember, u have to use free for free memory of the values. Also, you may don't free allocated memory if will end work right now.