Sprintf Does not work properly - xc8

Hello I am working on Pic18f46k22 with xc8 compiler.sprintf Function does not work properly.
My code is:
const char *DATA[4] = {"xxxxxx","yyyyyy","zzzzzz","aaaa"}
unsigned char Data1=2;
unsigned char Data2=3;
char L1Buffer[6];
char L2Buffer[6];
char TotalBuffer[20];
for(int i=0;i<6;i++){L1Buffer[i]=0;L2Buffer[i]=0;}
for(int i=0;i<20;i++){TotalBuffer[i]=0;}
sprintf (L1Buffer,"%s", DATA[Data1]);
sprintf (L2Buffer,"%s%d", DATA[Data2],Data2);
sprintf(TotalBuffer,"L1:%s L2:%s",L1Buffer,L2Buffer);
Lcd_Set_Cursor(2,1);
printf("%s",TotalBuffer);
Lcd_Set_Cursor(3,1);
printf("%s",L2Buffer);
Output :
L1:zzzzzzaaaa3 L2:aa
aaaa3
Expected output :
L1:zzzzzz L2:aaaa3
aaaa3

You are putting 7 characters (six 'z's + one '\0') into six character array. You need to take space for null terminator into account.
You need to declare L1Buffer to hold 7 characters:
unsigned char L1Buffer[7];
In your case, L1Buffer and L2Buffer are placed adjacent in memory. Writing "zzzzzz" into L1Buffer places six 'z's in L1Buffer and '\0' into L2Buffer[0], as it happens to be located right next to it:
z z z z z z\0 . . . . .
`-L1Buffer-'`-L2Buffer-'
Then, L2Buffer is overwritten:
z z z z z z a a a a 3\0
`-L1Buffer-'`-L2Buffer-'
Note there's no terminator after 'z's, so sprintf(TotalBuffer,"L1:%s L2:%s",L1Buffer,L2Buffer); takes L1Buffer values until it encounters nul lterminator at the end of L2Buffer. That's why you get zzzzzzaaaa3.

Related

Parsing an 8 bit char array to integer

I am new to Arduino and all I want to do is parse a String of binary numbers to an exact integer representation.
char* byte1 = "11111111"
int binary1 = atoi(byte1);
Serial.print(binary1);
However this prints out: -19961
Can anyone explain why? I am coming from a Java and JavaScript perspective.
atoi converts a decimal (base 10) string to int. If you want to convert a binary string to int, you can use strtol:
char *byte1 = "11111111";
int val1 = strtol(byte1, 0, 2);
std::cout << val1 << std::endl;
strtol can convert any base -- the 3rd argument is the base to use.
You get -19961 because on Arduino int is 16 bit wide and cannot hold any number bigger than 32767. To hold an integer representation of 11111111 you have to use long (which on Arduino is 32 bit) and strtol.
long val = strtol(byte1, NULL, 10);

Why does this binary math fail when adding 00000001, but work correctly otherwise?

I've tried everything I can think of and cannot seem to get the below binary math logic to work. Not sure why this is failing but probably indicates my misunderstanding of binary math or C. The ultimate intent is to store large integers (unsigned long) directly to an 8-bit FRAM memory module as 4-byte words so that a micro-controller (Arduino) can recover the values after a power failure. Thus the unsigned long has to be assembled from its four byte words parts as it's pulled from memory, and the arithmetic of assembling these word bytes is not working correctly.
In the below snippet of code, the long value is defined as four bytes A, B, C, and D (simulating being pulled form four 8-bit memory blocks), which get translated to decimal notation to be used as an unsigned long in the arrangement DDDDDDDDCCCCCCCCBBBBBBBBAAAAAAAA. If A < 256 and B, C, D all == 0, the math works correctly. The math also works correctly for any values of B, C, and D if A == 0. But if B, C, or D > 0 and A == 1, the 1 value of A is not added during the arithmetic. A value of 2 works, but not a value of 1. Is there any reason for this? Or am I doing binary math wrong? Is this a known issue that needs a workaround?
// ---- FUNCTIONS
unsigned long fourByte_word_toDecimal(uint8_t byte0 = B00000000, uint8_t byte1 = B00000000, uint8_t byte2 = B00000000, uint8_t byte3 = B00000000){
return (byte0 + (byte1 * 256) + (byte2 * pow(256, 2)) + (byte3 * pow(256, 3)));
}
// ---- MAIN
void setup() {
Serial.begin(9600);
uint8_t addressAval = B00000001;
uint8_t addressBval = B00000001;
uint8_t addressCval = B00000001;
uint8_t addressDval = B00000001;
uint8_t addressValArray[4];
addressValArray[0] = addressAval;
addressValArray[1] = addressBval;
addressValArray[2] = addressCval;
addressValArray[3] = addressDval;
unsigned long decimalVal = fourByte_word_toDecimal(addressValArray[0], addressValArray[1], addressValArray[2], addressValArray[3]);
// Print out resulting decimal value
Serial.println(decimalVal);
}
In the code above, the binary value should result as 00000001000000010000000100000001, AKA a decimal value of 16843009. But the code evaluates the decimal value to 16843008. Changing the value of addressAval to 00000000 also evaluates (correctly) to 16843008, and changing addressAval to 00000010 also correctly evaluates to 16843010.
I'm stumped.
The problem is that you're using pow(). This is causing everything to be calculated as a binary32, which doesn't have enough precision to hold 16843009.
>>> numpy.float32(16843009)
16843008.0
The fix is to use integers, specifically 65536 and 16777216UL.
Do not use pow() for this.
The usual way to do this is with the shift operator:
uint32_t result = uint32_t(byte3 << 24 | byte2 << 16 | byte1 << 8 | byte0);

About pointers and ASCII code

im learning more about c language and i have 1 doubt about 1 code that i have seen.
main(){
int i = (65*256+66)*256+67;
int* pi;
char* pc;
pi = &i;
pc = (char*)pi;
printf("%c %c %c \n", *pc, *(pc+1), *(pc+2));
}
Output is: C B A
I know that ASCII code of A is 65, B is 66, and C is 67 but the variable i is none of them.
If i put variable i=65, the output is just A and dont show B or C, why?
And i would like to know why this code have that output. Thanks for any help.
The line
int i = (65*256+66)*256+67;
turns i into the following
00000000 01000001 01000010 01000011
int = 4 bytes or 4 groups of 8 bits
char = 1 byte or 1 group of 8 bits.
What happens is that a char pointer is used to point to a subset of the original int bits.
At first the pointer points to the 8 least significant bits (the group to the right).
And the letter C is printed. Then, the pointer it self is incremented by 1 which makes it point to the next group of 8 bits in the memory which happens to be B. And once more for the A.
*256 means left shift by 8 bit (1 byte) so the line
int i = (65*256+66)*256+67;
actually put A,B,C on 3 adjacent bytes in memory
then pi pointer made point to the address of integer i, then same address down cast to char pointer pc, so pc actually hold the address to a byte that contains 'A', and of course if you add 1 and 2 to the address that means the adjacent 'B' and 'C' get pointed to and print out.
EDIT: just to clarify a bit more int is 32 bit long but char is 8 bit, that's why u need a char pointer to represent an address valid for 8 bit long.
Characters are stored as bytes, as you probably know. The initializing of the variable 'i' has the following meaning:
65*256 // store 65 ('A') and left shift it by 8 byte (= '*256')
(65*256+66)*256 // add 66 ('B') and shift the whole thing again
(65*256+66)*256+67 // add 67 ('C')
'pi' is initialized as a INT pointer to 'i'
'pc' is initialized as a CHAR pointer to 'pi'
So 'pc' then holds the address of the beginning of the 3 bytes stored in 'i', which holds 'A'.
By adding 1 and 2 to the address in pc, you get the second and third bytes (containing 'B' and 'C'), as follows:
printf("%c %c %c \n", *pc, *(pc+1), *(pc+2));
Working on the bits here ;D

pointer * and & difference

I am confused on pointers in objective-c. I wrote a very simple program to try and understand
char* temp = "temp";
printf("temp - %s \n", temp);
printf("*temp - %d \n", *temp);
printf("&temp - %s \n", &temp);
printf("&(*temp) - %s \n", &(*temp));
In this example, temp is a pointer to char with a default value of "temp". What does *temp, &temp mean? The output is:
temp - temp
*temp - 116
&temp - 00#
&(*temp) - temp
So temp is the pointer. When I print temp, it prints the value "temp". *temp is the value of the pointer or the address of the variable it points to. What is &temp? Is this the address of the pointer itself?
I wrote a second program in which I assign pointer to address of n (&n).
int n = 50, x;
int *ptr;
ptr = &n;
x = *ptr;
printf("n - %d\n", n);
printf("ptr - %d\n", ptr);
printf("*ptr - %d\n", *ptr);
printf("x - %d\n", x);
The output is:
n - 50
ptr - 2271924
*ptr - 50
x - 50
n is 50 and x is undefined. ptr points to address of n. Why does *ptr print 50 and *temp prints 116? Is the difference between how I have defined the two pointers? I am trying to understand the basics. Thank you.
When we print out *temp, we go to the temp variable, locate the address that it holds (the one it points to), than print out whatever data is in that location.
When we print out &temp, we are asking for the address of the temp variable, not what it is pointing to.
For your second program, you assign the address of n (using &) to ptr. This way, when we choose to call *ptr, it's gonna locate the address stored in ptr (which is n's), and print out whatever n holds. So you then assigned the value *ptr points to, and store it in x.
In summary, when declaring a pointer, & will print out the address of the variable, * will print out what it points to, and nothing in front will print out the address of the variable it's pointing to.

How can I use `vector <unsigned int*> vec;` properly

I am new in C++ and I want to use vector <unsigned int*> vec;
I try this code:
vector <unsigned int*> vec;
unsigned int* tmpV= new unsigned int[4];
for(unsigned int i=0; i<4;i++){
tmpV[i]=i;
}
vec.push_back(tmpV);
unsigned int* tmpV2=vec.at(0);
cout<<"A) tmpV2[1]: "<<tmpV2[1] <<endl;
cout<<"vec.size(): "<<vec.size()<<endl;
for(unsigned int i=0; i<4;i++){
tmpV[i]=i+4;
}
vec.push_back(tmpV);
tmpV2=vec.at(0);
cout<<"vec.size(): "<<vec.size()<<endl;
cout<<"B) tmpV2[1]: "<<tmpV2[1]<<endl;
The problem her is that I wanted to output the same value for A) and B)
but it ouputs
A) tmpV2[1]: 1
B) tmpV2[1]: 5
I want to be able to handle different elements in this vector of pointers.
I can roughly understand why this is going on but I couldn't find a solution.
Have in mind that I don't want to use: vector < vector <unsigned int> >
It is because you have incremented the value pointed by the pointer at the index a in vector
vec
if you reprint it again after printing
valuecout<<"B) tmpV2[1]: "<<tmpV2[1]<<endl
valuecout<<"B) tmpV2[1]: "<<vec[1] <<endl
both will show same result
What you have done so far is
You have a vector of integer pointers
You have initialized this array
You had one temporary pointer pointing to the zeroth index of the vector
Now using this pointer you printed the value pointed by the second index of the vec
After that you manipulated all the values pointed by vector of pointers (incremented by 4)
Now you are again printing the value pointed by index 1 of vector
Both are same only thing is you printed the value manipulated it and again printed after manipulation. If you reprint both *vec[1] and tmpV2[1] at the end again you will find both are same.

Resources