Truncated value is being stored - c

Here is my buffer and can any one explain how can i store a hexadecimal value inside this and when i try to print buffer[0], it is printing 0 instead of 500. I am trying to fill an element of the buffer with the ID which is of 11bits, I know the char is of 1 byte i.e.,8 bits and it cannot store the value. i have other elements to be filled into buffer and they are of type char. So i cannot change the type of the buffer from char to int. How can I solve my problem.
char *buffer;
buffer = (char *)malloc(10*(sizeof(frameRd))); //frameRd is of 16bytes
buffer[0] = frameRd->id;
for(int i =1;i<15;i++)
{
buffer[i] = frameRd->data;
}
for(int i =0,i<16;i++)
{
printf("%4X",buffer[i]);
}
where frame->id = 0x500; when i print this value on console, it is printing buffer[0] as 0 and surely because

Since buffer is char*, buffer[0] is char. Therefore, the assignment
buffer[0] = frameRd->id;
means "truncate frameRd->id to char, and store the result in buffer[0]," i.e. exactly the effect that you are observing. Moreover, when you print buffer[0] with %4X, you print the value of buffer[0] alone, converted to int.
If you want to get an int or a whole struct into a char[] buffer, use memcpy:
// Do not cast results of malloc
buffer = malloc(10*(sizeof(frameRd)));
// Save id into the buffer at index 0
memcpy(&buffer[0], &frameRd->id, sizeof(frameRd->id));
// Pull id back
int tmpId;
memcpy(&tmpId, &buffer[0], sizeof(tmpId));
printf("%04x\n", tmpId);
Demo.

Related

reading and printing unsigned int from file

I am trying to print and read unsigned ints from a .txt file. I am using fprintf to print the unsigend int, (menualy checking the file presents the wanted values), but when reading it, I get a weird offset to all the values I read (same offset beween all reads, but not every run of the program), here is the reading code I am using:
unsigned int tempDuration = (unsigned int)fileFgets(file);
and this is fileFgets:
char tempStr[MAX_STR_SIZE] = { 0 };
char* str = 0;
fgets(tempStr, MAX_STR_SIZE, file);
tempStr[strcspn(tempStr, "\n")] = 0;
str = (char*)malloc(strlen(tempStr) * sizeof(str));
strcpy(str, tempStr);
return str;
I am using this function becuse it is ment to read both strings and unsinged ints, seperated by '\n', but am open for using diffrent solutions for both or either. (reading the strings works as intended)
Casting from an array of characters to an unsigned integer will actually cast the pointer and not the string itself. You need to convert it using strtoul().
Replacing the '\n' character isn't required because strtoul stopps at the first character which is not a valid digit.
I modified your function :
unsigned int fileFgets(file)
{
char tempStr[MAX_STR_SIZE] = { 0 };
fgets(tempStr, MAX_STR_SIZE, file);
return strtoul(tempStr, NULL, 0);
}

Why isn't my 8-bit pointer updating correctly?

Directions are here:
I'm supposed to convert the ASCII string in the exact same input buffer, which is in this case pt1.
Unfortunately for me, the loop is executed only once and hence my output buffer only contains the first short value.
I'm trying to convert the ASCII string into a Unicode 16-bit string. According to the directions, pt1 is supposed to point to an ASCII string.
Expected Output is on this link.
https://i.stack.imgur.com/COpXl.jpg
void Convert(unsigned short *pt1) {
// pt1 is a pointer to a null-terminated variable length ASCII string
// 0x30 0x31 0x32 0x00 (sentinel value)
unsigned char *pt2 = (unsigned char *)pt1;
unsigned char value = *pt2;
while (*pt2 != 0x00) {
value = *pt2;
*pt1 = (unsigned short)value;
pt2++;
pt1++;
}
*pt1 = 0x0000;
}
There are multiple problems:
Your conversion function does not produce anything visible for the caller: you store code point values into a local array and return to the caller. The compiler warns you that at least pt3 is set and not used, but a more advanced compiler would optimise away all code for this function without a side effect.
What is the API description for Convert? You seem to receive a pointer to an ASCII string disguised as a pointer to unsigned short, and it seems the conversion should be performed in place. If this is the actual requirement, it is a very bad idea. The function should receive a pointer to a destination array with type unsigned short *, a size_t specifying the number of elements of this array and a pointer to the source string, with type const char *.
How should bytes outside the ASCII range be handled? Is the source string encoded in a given code page? it is UTF-8 encoded? Should the function report an error?
From the EDIT, you seem to confirm the insane API requirement. Assuming there is enough space in the argument array, you should perform the conversion from the last byte to the first, thus avoiding stepping on your own toes:
void Convert(unsigned short *pt1) {
// pt1 is a pointer to a null-terminated variable length ASCII string
// with enough space to receive the converted value including a null terminator
unsigned char *pt2 = (unsigned char *)pt1;
size_t i;
// Compute the number of bytes
for (i = 0; pt2[i] != '\0'; i++)
continue;
// Convert the contents from right to left
// Assuming ISO8859-1 encoding for bytes outside the ASCII range
for (;;) {
pt1[i] = (unsigned short)pt2[i];
if (i-- == 0)
break;
}
}

Convert char String to an int but not possible to convert a char from an char string to an int?

char input[5] = "12345";
printf("Convert to int valid %d", atoi(input));
printf("Convert to int invalid %d", atoi(input[1])); // program crash
Is there a solution to convert an char "slice" of an char string into an int?
Short description:
User inputs a string with values for example: 1, 2 3 4 ,5
Iam formating that string to 12345
With each number i want to continue to work with the index of an array.
If you mean "how to access a substring in the char [] array", you can use pointer arithmetic:
char input[6] = "12345";
printf("strtol(input + 1) = %d\n", strtol(input + 1, NULL, 10)); // Output = "2345";
Few things to note though:
Your array should be 6 elements long to hold the null terminator
atoi shouldn't be used at all; strtol is a better function for the task of converting a string to a signed integer; see here for more info.
Also, to convert a single character to an int:
if(isdigit(c))
{
c -= '0';
}
The relation that a textual representation of a digit is exactly '0' higher than the numeric value of that digit is guaranteed to hold for every character set supported by C.
To properly convert an arbitrary slice, you have to either make a copy or modify the string by inserting a \0 after the slice. The latter may not be an option, depending on where the string is stored.
To make a copy, allocate an array big enough to hold the slice and a \0. If you know the size of the slice at compile time, you can allocate on the stack:
char slice[2];
Otherwise, you'll have to allocate dynamically:
char *slice;
slice = malloc(2);
Stack allocated slices do not need to be deallocated, but dynamically allocated ones should be freed as soon as they are no longer needed:
free(slice);
Once you have the slice allocated, copy the portion of interest and terminate it with \0:
strncpy(slice, s + 1, 1);
slice[1] = '\0';
atoi(slice);
This technique will pretty much always work.
If your slice always ends with the string, you don't need to make a copy: you just need to pass a pointer to the start of the slice:
atoi(s + 1);
Modifying the string itself probably won't work, unless it's in writeable memory. If you're sure this is the case, you can do something like:
char tmp;
tmp = s[1];
s[1] = '\0';
atoi(s);
s[1] = tmp;
If you were sure but the memory wasn't writeable, your program will seg-fault.
For the special case where your slice is exactly one character long, you can use the fact that characters are numbers:
s[0] - '0'
Note that '0' !='\0' and that this won't work if your machine uses EBCDIC or similar.

Store an integer in a char array

I am trying to store an integer in a char array. How can I do that? This is my approach (by casting it the int to a char) but it does not work. What am I missing?
#include <stdio.h>
int main(int argc, char** argv)
{
char cArray[10] = {};
// Store a character in the char array
cArray[5] = 'c';
printf("%c\n", cArray[5]);
// Store an integer in the char array
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
}
Let's start with the basics.
For x86 architecture(assuming you use it) a char variable is stored in 1 byte and an int variable is stored in 4 bytes.
It is IMPOSSIBLE to store a random integer value in a char variable unless you have some compression schema and know that some integer values will not occur(no random!) in your program. No exceptions.
In your case, you want to store integers in a char array. There are four options:
1.If you want to store a random integer in this char array, then you should get the pointer to the index that you want to store the integer and cast it to an integer pointer and use it like that.
char mychars[10];
int * intlocation = (int*)(&mychar[5]);
*intlocation = 3632; // stores 3632
Beware that this will write to 4 bytes(4 char locations in your array) starting from the index you have specified. You should always check you are not going out of array.Also you should do the same casting for retrieving the value when needed.
2.If your values are between [0,255] or [-128,127] you can safely store your integers in a char since these ranges can be represented using a byte. Beware that char being signed or unsigned is implementation-dependent. Check this out!
mychars[5] = 54;
3.If your integer is just a digit, you can use the char representation of the digit.
mychars[5] = your_digit + 48; // 48 is the ascii code for '0'
4.If you want to store the string representation of your integer, then you should use itoa() and write each char of the resulting string to your array one by one. In that case, you should always check that you are not going out of array.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
This code attempts to print a character with the encoding 0; assuming ASCII, nothing will get displayed because there is no printable character associated with that code.
If you intend to store the ASCII code for the character '0' and print it, then you need to write
cArray[6] = 48; // same as writing cArray[6] = '0' (ASCII)
printf( "%c\n", cArray[6] );
This will print 0 to your console.
If, on the other hand, you want to store any arbitrary integer value1 to cArray[6] and display that value, then you need to use the %d conversion specifier:
cArray[6];
printf( "%d\n", cArray[6] );
1. That is, any integer that fits into the range of char, anyway
Normally, a computer exactly does what you tell it. The instruction DWIM (do what I mean) hasn't been invented yet.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
sets the index position 6, but
printf("%c\n", cArray[5]);
prints the index position 5.
I would like to add on to Seçkin Savaşçı's answer (in which you cast a char* pointer to somewhere in the char array to an int* pointer, allowing you to write an integer to the array by dereferencing the pointer).
You can also use bit-shifting:
#include <stdio.h>
int main() {
int first_int = 4892; // number larger than 127 (max. value of char)
int second_int = 99584; // same
// char array to hold two integers:
char array[8]; // ...assuming an integer size of 4 and char size of 1
// Now, assuming you are on a little endian system (in which the least
// significant bytes come first), you can add the two above integers to the
// array like so:
array[0] = first_int; // assigns first_int's least significant byte
array[1] = first_int >> 8; // assigns first_int's 2nd least significant byte
array[2] = first_int >> 16; // assigns first_int's 2nd most significant byte
array[3] = first_int >> 24; // assigns first_int's most significant byte
// repeat for second_int:
array[4] = second_int;
array[5] = second_int >> 8;
array[6] = second_int >> 16;
array[7] = second_int >> 24;
// You can now prove that this char array holds the two integers like this:
printf("First integer: %d\n", *((int *) array));
printf("Second integer: %d\n", *((int *) (array + 4)));
return 0;
}
On a big endian system you would first assign the most significant byte, and move on to the least significant bytes.
Replace
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[5]);
By
cArray[6] = (char)51;
printf("%c\n", cArray[6]);
Should display '3'
I think you will understand your mistake... 0 as int does not represent the printable character '0', but the NULL termination string
51 as int represent the character '3'
You may use itoa(0,&cArry[6],10).
Use the correctly desired format specifier.
cArray[6] = (char) 0; does store an integer 0 into array element cArray[6]. Its the printf() that is fooling OP into thinking that did not work.
Using %c says OP wants the character that is encoded with a 0. (It usually not visible). Use %d to print the integer value of cArray[6].
printf("%d\n", cArray[6]);
You can add the ASCII value of 0 to the value you want to store digit into the character array.
For example if you want to store 0,1,...,9 into the character array A[10], you may use the following code.
for(j = 0; j<k; j++)
{
A[j] = j + '0'; // Same effect if you use A[j] = j + 0x30
}
This works only if the integer you want to store is less than 10. Otherwise you will have to extract the digits using modulo operator and store.

How to convert an Unsigned Character array into a hexadecimal string in C

Is it possible to represent an unsigned character array as a string?
When I searched for it, I found out that only memset() was able to do this (But character by character).
Assuming that is not the correct way, is there a way to do the conversion?
Context: I am trying to store the output of a cryptographic hash function which happens to be an array of unsigned characters.
eg:
unsigned char data[N]; ...
for(i=0;i<N;i++) printf("%x",data[i]);
My goal is to represent the data as a String (%s) rather than access it by each element. Since I need the output of the hash as a String for further processing.
Thanks!
So, based on your update, are you talking about trying to convert a unsigned char buffer into a hexadecimal interpretation, something like this:
#define bufferSize 10
int main() {
unsigned char buffer[bufferSize]={1,2,3,4,5,6,7,8,9,10};
char converted[bufferSize*2 + 1];
int i;
for(i=0;i<bufferSize;i++) {
sprintf(&converted[i*2], "%02X", buffer[i]);
/* equivalent using snprintf, notice len field keeps reducing
with each pass, to prevent overruns
snprintf(&converted[i*2], sizeof(converted)-(i*2),"%02X", buffer[i]);
*/
}
printf("%s\n", converted);
return 0;
}
Which outputs:
0102030405060708090A
In C, a string is an array of char, terminated with a character whose value is 0.
Whether or not char is a signed or unsigned type is not specified by the language, you have to be explicit and use unsigned char or signed char if you really care.
It's not clear what you mean by "representing" an unsigned character array as string. It's easy enough to cast away the sign, if you want to do something like:
const unsigned char abc[] = { 65, 66,67, 0 }; // ASCII values for 'A', 'B', 'C'.
printf("The English alphabet starts out with '%s'\n", (const char *) abc);
This will work, to printf() there isn't much difference, it will see a pointer to an array of characters and interpret them as a string.
Of course, if you're on a system that doesn't use ASCII, there might creep in cases where doing this won't work. Again, your question isn't very clear.
Well a string in C is nothing else than a few chars one after another. If they are unsigned or signed is not much of a problem, you can easily cast them.
So to get a string out of a unsigned char array all you have to do is to make sure that the last byte is a terminating byte '\0' and then cast this array to char * (or copy it into a array of char)
I successfully use this to convert unsigned char array to std:string
unsigned char array[128];
std::stringstream buffer;
for (int i = 0; i < 128; i++)
{
buffer << std::hex << std::setfill('0');
buffer << std::setw(2) << static_cast<unsigned>(array[i]);
}
std::string hexString = buffer.str();
An example as you've asked:
unsigned char arr [SIZE];

Resources