Writing one byte in struct variable - c

I'm trying to modify one byte of my structure with the following code :
struct example *dev;
PRINT_OPAQUE_STRUCT(dev);
sprintf((char*) dev + 24, "%x",1);
PRINT_OPAQUE_STRUCT(dev);
The PRINT_OPAQUE_STRUCT is just printing the content of the structure, and is defined in this other topic :
Print a struct in C
The output of this program is :
d046f64f20b3fb4f00000000e047f64f00000000ffffffff000000
d046f64f20b3fb4f00000000e047f64f00000000ffffffff310000
I don't know why I have the value "31" written and not the value "01" as wanted. I tried to replace the second argument of sprintf with "%01x" but it didn't change anything. Anyone knows why?
Thanks!

Well, you are formatting the value 1 as a string. That's what sprintf does. 0x31 is the character code for the character '1'. If you just want to write the byte value 0x01 into your struct, then you don't need sprintf. Just do this:
*((char*)dev + 24) = 1;
or (the same, but with slightly different syntax):
((char*)dev)[24] = 1;
Note also, like one comment below says, sprintf will not just write one single byte. Since it writes a string, and C strings are null-terminated, it will also write a null character ('\0', 0x00) right after the '1'.

I don't know why I have the value "31" written and not the value "01" as wanted.
The reason you see 31 is that your chain of functions interprets the value 1 twice:
First, sprintf interprets it as a character representing a hex digit
Second, PRINT_OPAQUE_STRUCT interprets the value again, now as a hex number
Essentially, sprintf converts 1 to its character representation, which is '1'. On your system, its code is 0x31, hence the output that you get.
You need to remove one of these two interpretations to get your code to print 1. To remove the first interpretation, simply assign 1 to the pointer, like this:
((char*)dev)[24] = 1;
To remove the second interpretation, print with %c instead of %x in PRINT_OPAQUE_STRUCT (which may not be possible).

Related

Objective-c: Why is strtol method used in this code I inherited?

I recently inherited some Objective-C code and am really confused as to what it's actually doing?
1) I don't understand why the char byte_chars[3] is being populated by a '0' first and then a 0 at the end?
2) I don't understand why they used unsigned char for the wholeByte, but the put a long into it?
3) Part of me is a little confused as to what the strtol method does here, it takes 3 byte_chars bytes (which are hexadecimal), and then converts them to a long?
- (NSString *)starFromFlags:(NSString *)flags {
unsigned char wholeByte;
char byte_chars[3];
NSString *star = #"NO";
byte_chars[0] = '0';
byte_chars[1] = [flags characterAtIndex:1];
byte_chars[2] = 0;
wholeByte = strtol(byte_chars, NULL, 16);
if (wholeByte & 0x01) star = #"YES";
return star;
}
To 1:
The 0 at the end is a '\0' (both value of zero) at the end, which means "string ends here". You have to put it at the end to end the string.
The '0' (letter 0) at the begin signals a octal value (not hexadecimal, that would be "0x") for strtol(). But as correctly mentioned by CRD (see comments), it is overriden here by the third arg passed to strtol(). So up to here you have a two-letter string with 0 the first character and the hexadecimal representation of the flags as the second character.
The reason for this is probably, that flags contains a digit from '0' to 'f'₁₆/'F'₁₆ (0 to 15₁₀).
To 2:
Since the values that can outcome from the conversion are in the range [0…15] the long value will have one of this values. You can store it in a single byte and do not need a whole long. However, strtol() always returns a long.
To 3:
Yes, it is a conversion from a string containing a number into a number. I.e. the string "06" will be converted to the number 6.
Amin Negm-Awad has explained what the code does (with a minor confusion over octal), but as to answering your question:
Why is strtol method used in this code I inherited?
we can only guess.
It appears that the second character in the string is a hexadecimal digit being used for (up to) 4 flag bits, the method is testing whether the least significant of these is set. A simpler way to do this might be:
- (NSString *)starFromFlags:(NSString *)flags
{
unichar flag = [flags characterAtIndex:1];
if (flag > 127 || !isxdigit(flag)) // check flag is in ASCII range and hex digit
return #"INVALID";
else
return digittoint(flag) & 0x1 ? #"YES" : #"NO"; // check if flag is odd hex
}
isxdigit() and digittoint() are C library functions (just like strtol()), use man isxdigit in the Terminal for the documentation (unless you are using an older version of Xcode which has the documentation for these, Apple unhelpfully removed the docs in the latest versions). The first checks if a character is a hexadecimal digit, the second returns the integer equivalent. The > 127 check is minimal protection against non-"ASCII" characters in your string.
Note: An NSString (presents itself as) as sequence of UTF-16 code units so characterAtIndex: returns a unichar (a 16-bit type) hence the type of flag. However this code doesn't handle any unicode string correctly. If your strings are "ASCII" it will work.
The above function actually does more error checking than the original, if you are happy to reduce the error checking you can just use:
- (NSString *)starFromFlags:(NSString *)flags
{
return digittoint([flags characterAtIndex:1]) & 0x1 ? #"YES" : #"NO";
}
This will return #"YES" if and only if the flag is a hex digit and its LSB is set, if it isn't a hex digit or the LSB isn't set it returns #"NO". This works because digittoint() returns 0 if its argument isn't a hex digit.
So why did the original programmer use strtol()? Maybe they didn't know about digittoint().
HTH

read 2 bytes in hexadecimal base and convert into decimal using C language fscanf

Well as said Im using C language and fscanf for this task but it seems to make the program crash each time then its surely that I did something wrong here, I havent dealed a lot with this type of input read so even after reading several topics here I still cant find the right way, I have this array to read the 2 bytes
char p[2];
and this line to read them, of course fopen was called earlier with file pointer fp, I used "rb" as read mode but tried other options too when I noticed this was crashing, Im just saving space and focusing in the trouble itself.
fscanf(fp,"%x%x",p[0],p[1]);
later to convert into decimal I have this line (if its not the EOF that we reached)
v = strtol(p, 0, 10);
Well v is mere integer to store the final value we are seeking. But the program keeps crashing when scanf is called or I think thats the case, Im not compiling to console so its a pitty that I cant output what has been done and what hasnt but in debugger it seems like crashing there
Well I hope you can help me out in this, Im a bit lost regarding this type of read/conversion any clue will help me greatly, thanks =).
PS forgot to add that this is not homework, a friend want to make some file conversion for a game and this code will manipulate the files needed alone, so while I could be using any language or environment for this, I always feel better in C language
char strings in C are really called null-terminated byte strings. That null-terminated part is important, as it means a string of two characters needs space for three characters to include the null-terminator character '\0'. Not having the terminator means string functions will go out of bounds in their search for it, leading to undefined behavior.
Furthermore the "%x" format is to read a heaxadecimal integer number and store it in an int. Mismatching format specifiers and arguments leads to undefined behavior.
Lastly and probably what's causing the crash: The scanf family of function expects pointers as their arguments. Not providing pointers will again lead to undefined behavior.
There are two solutions to the above problems:
Going with code similar to what you already use, first of all you must make space for the terminator in the array. Then you need to read two characters. Lastly you need to add the terminator:
char p[3] = { 0 }; // String for two characters, initialized to zero
// The initialization means that we don't need to explicitly add the terminator
// Read two characters, skipping possible leading white-space
fscanf(fp," %c%c",p[0],p[1]);
// Now convert the string to an integer value
// The string is in base-16 (two hexadecimal characters)
v = strtol(p, 0, 16);
Read the hexadecimal value into an integer directly:
unsigned int v;
fscanf(fp, "%2x", &v); // Read as hexadecimal
The second alternative is what I would recommend. It reads two characters and parses it as a hexadecimal value, and stores the result into the variable v. It's important to note that the value in v is stored in binary! Hexadecimal, decimal or octal are just presentation formats, internally in the computer it will still be stored in binary ones and zeros (which is true for the first alternative as well). To print it as decimal use e.g.
printf("%d\n", v);
You need to pass to fscanf() the address of a the variable(s) to scan into.
Also the conversion specifier need to suite the variable provided. In your case those are chars. x expects an int, to scan into a char use the appropriate length modifiers, two times h here:
fscanf(fp, "%hhx%hhx", &p[0], &p[1]);
strtol() expects a C-string as 1st parameter.
What you pass isn't a C-string, as a C-string ought to be 0-terminated, which p isn't.
To fix this you could do the following:
char p[3];
fscanf(fp, "%x%x", p[0], p[1]);
p[2] = '\0';
long v = strtol(p, 0, 10);

In C, check for the offset in a character string and count the number of bytes

Further help on my assignment I asked about earlier. After reading a character string from stdin, it checks for any non-ascii characters. Any it finds will display it's value in hexadecimal and the zero offset. I got it to display the hexadecimal just fine, but I'm having a hard time figuring out how to display the offset. This is my current code for it as of asking this question, showing only the relevant lines.
#define MASK 0x80
auto int inChar;
if ((inChar & MASK) == MASK)
{
printf("NON-ASCII INPUT: %x detected at offset %#x \n", inChar, inChar);
nonascii = 1;
}
There is another thing I need help with, hopefully this will be easier to answer though. If the line read has nothing but ASCII, it is to write out as such and display the total number of bytes read. I know how to do this with integers and multiplication by simply counting the number of times a do while is done, but the professor seems to want us to do it in a more direct manner.
This is my code for that as of writing.
if (nonascii == 0)
printf("The input stream was pure ASCII with a total of %d bytes read", (numBytes &= inChar));
Much thanks to those who help me with this.
inChar contains the value of the character read; it does not carry information about where in the string the character is, therefore it is not possible to figure out the offset from this variable.
The place to look at is wherever you fill inChar with the current character; unfortunately, we do not see that part of the code. Most likely, at that point, you are extracting the value from a certain index in the string and you should just use the same index variable for displaying the offset. Another possibility is that you are extracting the value from the string by moving a pointer within the string. In that case, the way to extract the offset is by using pointer arithmetic: say that you have pointer string that points to the beginning of the string and stringIter that points at the currently processed character, then looking at how far the pointers are from each other will tell you your offset in the string: stringIter - string.
inChar is a character, not an offset. Offset means the array index of where the character was found in the string, and you should probably print it as decimal using the %d formatter.
The simplest way to display a string's length is with the strlen() function. But if you're not allowed to use that, then the length of the string is the array index + 1 when you fall out of the loop.

How to create array with hex chars from array of numbers

I have array of chars:
char macChars=[12];
The content of it is e.g. macChars[0]=53, macChars[1]=66 ...
I need to convert these numbers to hex chars, so i would have another array:
macCharsHex[0]=5 //value 53 in hex
macCharsHex[1]=B //value 66 in hex
Thank you.
Assuming ASCII, your example already does contain the values you want them to contain. So you don't have to convert anything. Maybe you want to print them?
This should work:
char hex[255] = {0}; // Varible to hold the hex value
int dec = 1234; // Decimal number to be converted
sprintf(hex,"%X", dec);
printf("%s", hex); // Print hex value
Use sprintf(), for instance. Note that it will take more space, if you have 12 bytes you will need 24 + 1 bytes for the string representation, since each byte requires two characters in hex and then the terminating '\0'-byte.
I suspect that I don't understand the question at all, especially not the example given.
If you have macChars[0] == 53, which is 0x35 in hex, then I would expect to get maxCharsHex[0] == '3' and macCharsHex[1] == '5' after the first char has been converted. This is done like so with sprintf():
sprintf(maxCharsHex, "%02x", (int) macChars[0] & 0xff);
The cast and mask is to be on the safe side for signed characters.
They are already converted, since character in C are represented by their corresponding character codes.
Therefore, as far as storing things in arrays is concerned there is nothing you need to do and if you want "5" and "B" to show up correctly when printing or doing something like that its a matter of using the correct printing function (putchar, printf with %c, etc).

Usage of function putc

I am working on a C program that I did not write and integrating it with my C++ code. This C program has a character array and usage putc function to print the content of it. Like this:
printf("%c\n","01"[b[i]]);
This is a bit array and can have either ASCII 0 or ASCII 1 (NOT ASCII 48 and 49 PLEASE NOTE). This command prints "0" and "1" perfectly. However, I did not understand the use of "01" in the putc command. I can also print the contents like this:
printf("%d\n",b[i]);
Hence I was just curious. Thanks.
Newbie
The "01" is a string literal, which for all intents and purposes is an array. It's a bit weird-looking... you could write:
char *characters = "01";
printf("%c\n", characters[b[i]]);
or maybe even better:
char *characters = "01";
int bit = b[i];
printf("%c\n", characters[bit]);
And it would be a little easier to understand at first glance.
Nasty way of doing the work, but whoever wrote this was using the contents of b as an array dereference into the string, "01":
"foo"[0] <= 'f'
"bar"[2] <= 'r'
"01"[0] <= '0'
"01"[1] <= '1'
your array, b, contains 0s and 1s, and the author wanted a way to quickly turn those into '0's and '1's. He could, just as easily have done:
'0' + b[i]
But that's another criminal behavior. =]
The String "01" is getting cast into a character array (which is what strings are in C), and the b[i] specifies either a 0 or a 1, so the "decomposed" view of it would be.
"01"[0]
or
"01"[1]
Which would select the "right" character from the char array "string". Note that this is only possible C due to the definition that a string is a pointer to a character. Thus, the [...] operation becomes a memory offset operation equal to the size of one item of the type of pointer (in this case, one char).
Yes, your printf would be much better, as it requires less knowledge of obscure "c" tricks.
This line is saying take the array of characters "01" and reference an array element. Get that index from the b[i] location.
Thus "01"[0] returns the character 0 and "01"[1] returns the character 1
Do the statement you understand.
Simplifying the other one, by replacing b[i] with index, we get
"01"[index]
The string literal ("01") is of type char[3]. Getting its index 0 or 1 (or 2) is ok and returns the character '0' or '1' (or '\0').

Resources