c language type conversion - pointers

I'm not able to understand the output of this simple c code.What happens when we typecast a int value to char pointer?
int main(void) {
int a =320;
char *ptr;
ptr=(char *)&a;
printf("%d",*ptr);
return 0;
}
the output is 64.But I'm unable to figure out the logic.Does the size of the signed char play a role here?

320 is 0x140 in hex. A char is one byte (Two hexadecimal digits), so casting and printing with %d will print the decimal value of 0x40, which happens to be 64.

Related

QString to qint16

I am trying to convert a QString to a qint16 with
udpListenPort = ui->lineEdit_UdpListenPort->text().toShort();
but it converts "40690" to 0.
I tried different casts and conversions but neither works. I think I can't see the wood for the trees here.
The maximal value a qint16 (which is a typedef short qint16; /* 16 bit signed */) can hold is 32767 using two's complement, hence "40690" overflows and signed integer overflow is undefined behaviour.
Use quint16 instead (which is a typedef unsigned short quint16; /* 16 bit unsigned */) and ushort QString::toUShort(bool *ok = nullptr, int base = 10) const.
You came most of the way, just change the toShort() to toUShort() to fix that.
udpListenPort = ui->lineEdit_UdpListenPort->text().toUShort();
quint16 is just a typedef for unsigned short.

Converting from void * to float

I have a pointer to some location in memory passed in, void *dataLoc.
Some program is transferring memory there as a bunch of unsigned chars where 0x00 is 0 and 0xFF is one.
I want to be able to pull, say, every 4th char and convert it to the float of what number is supposed to be represented. But I'm having trouble understanding how I get from a void * to an array of char[] to an array of float[].
My initial thought was to do something like
for(i=0,i<100,i++){
floatArray[i] = (float)(*((unsigned char *)dataLoc[4*i])) / 255;
}
the void * is cast to a char *.
the next 4th char is selected from the for loop
the * dereferences the char pointer, which should give me an unsigned char,
the float should change the char into a float, but a float representation of the number I want *255
I divide by 255 to get the fraction I want.
This fails, because I get the error "pointer of type 'void ' used in arithmetic
'void' is not a pointer-to-object type and beyond this, I'm not really confident that the rest of that line will work out the way I would like.
Can someone advise the proper way to handle this?
Good that you had warnings enabled.
dataLoc[4*i] occurs before (unsigned char *)dataLoc and leads to "pointer of type 'void *' used in arithmetic ..."
Cast to unsigned char * first.
Also remove extra level of *. The following is type unsigned char
((unsigned char *)dataLoc)[4*i]
Fixed:
void * dataLoc;
float floatArray[100];
// for(i=0,i<100,i++){ Use ';', not ','
for(int i=0;i<100;i++){
// Cast to `unsigned char *` before using `[]`
// * not needed here ---v
floatArray[i] = (float)( ( ((unsigned char *)dataLoc) [4*i])) / 255;
}
or
for (int i=0; i<100 ;i++) {
unsigned char value = ((unsigned char *)dataLoc)[4*i];
floatArray[i] = value / 255.0f;
}

Failing to convert raw binary/hex to int interpretation

I'm trying to convert raw hex/binary data to different file types.
#include <QByteArray>
#include <QDebug>
int main(int argc, char *argv[])
{
QByteArray package;
package.append( QByteArray::fromHex("a1"));
// "a1" is what is written to the memory, not the string representation of "a1"
qDebug() << package.toHex(); // "a1"
qDebug() << package; // "�"
qDebug() << package.toInt(); // 0
}
Why is the int representation 0 and not 161?
toInt has totally different purpose. It parses string representation of integer. If you want integer representing the value of the first byte of the array, use package[0]. It has char type. I don't remember how qDebug() represents char type, but if you have any problems with it, just static_cast it to unsigned int.
QByteArray::toInt expects that QByteArray contains a string of characters (in ASCII probably), not the binary representation of the number.
If you want to convert binary representation to integer you can use reinterpret_cast:
int i = *reinterpret_cast<quint8*>(package.constData());
Or better use qFromBigEndian/qFromLittleEndian:
int i = qFromLittleEndian<quint8>((const uchar*)package.constData())
In both cases you must know exactly in what format the number is stored and use proper type and endianness.

Struct Stuffing Incorrectly

I have the following struct:
typedef union
{
struct
{
unsigned char ID;
unsigned short Vdd;
unsigned char B1State;
unsigned short B1FloatV;
unsigned short B1ChargeV;
unsigned short B1Current;
unsigned short B1TempC;
unsigned short B1StateTimer;
unsigned short B1DutyMod;
unsigned char B2State;
unsigned short B2FloatV;
unsigned short B2ChargeV;
unsigned short B2Current;
unsigned short B2TempC;
unsigned short B2StateTimer;
unsigned short B2DutyMod;
} bat_values;
unsigned char buf[64];
} BATTERY_CHARGE_STATUS;
and I am stuffing it from an array as follows:
for(unsigned char ii = 0; ii < 64; ii++) usb_debug_data.buf[ii]=inBuffer[ii];
I can see that the array has the following (arbitrary) values:
inBuffer[0] = 80;
inBuffer[1] = 128;
inBuffer[2] = 12;
inBuffer[3] = 0;
inBuffer[4] = 23;
...
now I want display these values by changing the text of a QEditLine:
str=QString::number((int)usb_debug_data.bat_values.ID);
ui->batID->setText(str);
str=QString::number((int)usb_debug_data.bat_values.Vdd)
ui->Vdd->setText(str);
str=QString::number((int)usb_debug_data.bat_values.B1State)
ui->B1State->setText(str);
...
however, the QEditLine text values are not turning up as expected. I see the following:
usb_debug_data.bat_values.ID = 80 (correct)
usb_debug_data.bat_values.Vdd = 12 (incorrect)
usb_debug_data.bat_values.B1State = 23 (incorrect)
seems like 'usb_debug_data.bat_values.Vdd', which is a short, is not taking its value from inBuffer[1] and inBuffer[2]. Likewise, 'usb_debug_data.bat_values.B1State' should get its value from inBuffer[3] but for some reason is picking up its value from inBuffer[4].
Any idea why this is happening?
C and C++ are free to insert padding between elements of a structure, and beyond the last element, for whatever purposes it desires (usually efficiency but sometimes because the underlying architecture does not allow unaligned access at all).
So you'll probably find that items of two-bytes length are aligned to two-byte boundaries, so you'll end up with something like:
unsigned char ID; // 1 byte
// 1 byte filler, aligns following short
unsigned short Vdd; // 2 bytes
unsigned char B1State; // 1 byte
// 3 bytes filler, aligns following int
unsigned int myVar; // 4 bytes
Many compilers will allow you to specific how to pack structures, such as with:
#pragma pack(1)
or the gcc:
__attribute__((packed))
attribute.
If you don't want to (or can't) pack your structures, you can revert to field-by-filed copying (probably best in a function):
void copyData (BATTERY_CHARGE_STATUS *bsc, unsigned char *debugData) {
memcpy (&(bsc->ID), debugData, sizeof (bsc->ID));
debugData += sizeof (bsc->ID);
memcpy (&(bsc->Vdd), debugData, sizeof (bsc->Vdd));
debugData += sizeof (bsc->Vdd);
: : :
memcpy (&(bsc->B2DutyMod), debugData, sizeof (bsc->B2DutyMod));
debugData += sizeof (bsc->B2DutyMod); // Not really needed
}
It's a pain that you have to keep the structure and function synchronised but hopefully it won't be changing that much.
Structs are not packed by default so the compiler is free to insert padding between members. The most common reason is to ensure some machine dependent alignment. The wikipedia entry on data structure alignment is a pretty good place to start. You essentially have two choices:
insert compiler specific pragmas to force alignment (e.g, #pragma packed or __attribute__((packed))__.
write explicit serialization and deserialization functions to transform your structures into and from byte arrays
I usually prefer the latter since it doesn't make my code ugly with little compiler specific adornments everywhere.
The next thing that you are likely to discover is that the byte order for multi-byte integers is also platform specific. Look up endianness for more details

Invalid conversion from char to 'uint8_t'

I'm using a shift out statement to drive a few 7 seg displays (in the end)
but I'm running into a problem.
I have used #include <avr/pgmspace.h> libary as to save space for the processing.
At the end of it I need to shiftOut a binary number to be fed into a reg then to a BCD then to my display:
strcpy_P(buffer, (char*)pgm_read_word(&(Times[big])));
shiftOut(dataPin, clockPin, MSBFIRST, buffer);
in the buffer place will go the selected value (e.g. B00100011 should display 23),
my code gives me
Invalid conversion from char to 'uint8_t'
with the shiftOut line highlighted
Any ideas?
The problem here is that shiftOut expects a byte (uint8_t) as its 4th argument (value). The passed value is a char* (presumably declared as a prog_char array).
To fix this, the declaration of the value will need to use prog_uchar, like this:
prog_uchar values[] PROGMEM = { (prog_uchar) B00100011, ... };
...
int valueIndex = ...; // Index of value in the values array
shiftOut(dataPin, clockPin, MSBFIRST, pgm_read_byte(&(values[valueIndex])));

Resources