Edit: I am not sure if this code does what I think it does. Could someone tell me how to test it? I.e. what should the buffer in my main function look like? I am assuming that a buffer has data of two fields in the following order type(16 bits), length(32 bits). I'm assuming that the buffer is read in from a file and each of the fields is separated by a space. The fields are stored in network byte order and when I read them I have to convert them back to host byte order.
I'm expecting that the code will read the contents from the file (which should be in network byte order) and display the contents in host byte order. I'm a bit confused about type conversions and what the network byte order will be inside of a file, so I don't know what values to use to test it. Also, I'm not sure if my code is written correctly, could someone who does this sort of thing or knows a bit more about such conversions tell me if my code is correct?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printRecords(char *buffer)
{
unsigned int recordType;
unsigned long recordLength;
char *data;
char *index;
if (!buffer)
printf("Empty buffer\n");
while(*buffer)
{
memcpy(&recordType,(const void *) buffer,2);
buffer += 3;
recordType = ntohs(recordType);
printf("Record type normal: %u\n",recordType);
memcpy(&recordLength,(const void *) buffer,4);
buffer += 5;
recordLength = ntohl(recordLength);
printf("Record Length normal: %l\n",recordLength);
break;
}
}
void main()
{
char * buffer = "0000000000000001 00000000000000000000000000000001";
printRecords(buffer);
}
char *buffer = malloc(sizeof(buf));
sizeof means "size of buf's type", ie the size of a pointer to char; you probably want
malloc(strlen(buf) + 1); /* 1 for trailing '\0' */
Then you are mistaking the value of the bytes for their conversion to string:
"256" is byte '2' followed by byte '5' and '6' -- '2' is not equals to 2, '5' is not equals to 5 etc.
The 256 you are talking about is 00000001 00000000 instead (try dumping the bytes to stdout and you'll see).
Also, recordType should be of type uint16_t, not unsigned -- you're never too paranoid.
EDIT: atoi takes a pointer to char, as in
atoi("123")
not a pointer to int!
Related
I have a struct carrying multiple members with different type. I want to copy this struct to a buffer, then concatenate a message for later use (separate them and read the struct and message, which I didn't do it here). Here is my code.
#define DAT "d"
#define ACK "a"
#define SYN "s"
#define FIN "f"
#define RST "r"
typedef struct Headers { //total 20 bytes
unsigned char _magic_[7];
unsigned char _type_[1];
union {
unsigned int _seq_; //4 bytes
unsigned int _ack_; //4 bytes
} no;
unsigned int _length_; //4 bytes
unsigned short _size_; //2 bytes
} Header;
int main() {
Header receiver_header;
char buffer[1024];
strcpy(receiver_header._magic_, "ABCDEF");
strcpy(receiver_header._type_, DAT);
receiver_header.no._ack_ = 0;
receiver_header._length_ = 900;
receiver_header._size_ = 10240;
char foo[] = "A random message";
memcpy(buffer, &receiver_header, sizeof(Header));
strcat(buffer, foo);
printf("%s\n", buffer);
}
And the output is
ABCDEFA random message
My questions are
Do you need to cast the members to same type in order to copy them into the buffer?
Why is the rest of the members disappeared in the buffer even I have declared the correct pointer of the source and length of it?
The first member of your Header, _magic_, holds 7 chars. You copied 6 chars ("ABCDEF") followed by a null character. strcat copies the source string into the destination string at the first null character it encounters. Therefore, it appends "A random message" right after the first six bytes of the Header. If you want to append the message after the entire struct, you need to specify an offset to copy to, like so.
strcpy(buffer + sizeof(Header), foo);
However, it won't print the entire struct since the null character is still right after "ABCDEF", even though foo has been appended at the correct offset. If you want to print everything in your struct, just print out each member explicitly, like so.
printf("%s %c %u %u %hu %s",
receiver_header._magic_,
receiver_header._type[0],
reveiver_header.no._ack_,
receiver_header._length_,
receiver_header._size_,
foo);
Do you need to cast the members to same type in order to copy them into the buffer?
No. memcpy() can copy the whole representation of any object. But you do have some other apparent misconceptions and strangeness:
If Header._magic_ is meant to hold a string then its element type should be char, not unsigned char. On the other hand, if it's meant to hold binary data then you should not use strcpy() to copy data into it.
Header._type_ has space for a single byte, but you strcpy() a one-character string into it. The string requires two bytes when you count the terminator; these don't both fit into _type_. Probably you should perform an ordinary assignment of a single (unsigned) char instead.
The struct representation that you copy into the buffer is not collectively the contents of a C string, if only on account of having internal null bytes. Therefore, you cannot safely append to it with strcat(). More generally, you ought not be manipulating general data with string functions.
It is also unreasonable to try to print the structure representation as if it were a string. Even if there were no internal null bytes, but there were a terminating null byte, your struct has numeric fields. Their representation is binary, not textual, and printing them as if they were textual will not produce anything useful.
Why is the rest of the members disappeared in the buffer even I have declared the correct pointer of the source and length of it?
Because you overwrote them when you strcat()ed the message onto the buffer.
I need to read a single byte from a file. Normally when reading, I use a char array as the buffer. However, I need to be able to perform binary operations with byte, which can't be done with a char array. Here's what I've got:
read(file, buffer, 1);
I've tried making buffer both a char and an int, but both give me warnings that it expects a void * argument. But of course, that doesn't allow for binary operations like &.
How can I store buffer such that I can perform binary operations on it?
You could use the function int fgetc (FILE *fp).
The return value will be an int value from 0 to 255 or EOF.
You can read into a char array as you (supposedly) know how to do, and then perform your binary operations on the first element of that array.
Binary operation can be performed on char data type with unsigned. Even if its an array binary operation can be done to the single element of the array.
for your reference.
ssize_t read(int fd, void *buf, size_t count);
buffer has to be address of the character or character array, in your single char is sufficient. If you want to use array use the element array[0] and perform operation on that.
As mentioned in the comments above
unsigned char c;
read(file, &c, 1);
typedef unsigned char uint8_t; /* Not necessary if you are using C99, i.e. <stdint.h>. */
uint8_t buffer[BUF_SIZE] = {0};
.
.
.
if (fread(buffer, sizeof(buffer[0]), 1, file) == 1)
{
buffer[0] ^= 0xFFu; /* Or any other bit-wise operation. */
}
Refer -
1. https://linux.die.net/man/3/fread
2. http://en.cppreference.com/w/c/types/integer
I have a thread which parses incomming characters/bytes one by one.
I would like to store the sequence of bytes in a byte pointer, and in the end when the sequence of "\r\n" is found it should print the full message out.
unsigned char byte;
unsigned char *bytes = NULL;
while (true){ // thread which is running on the side
byte = get(); // gets 1 byte from I/O
bytes = byte; //
*bytes++;
if (byte == 'x'){ // for now instead of "\r\n" i use the char 'x'
printf( "Your message: %s", bytes);
bytes = NULL; // or {0}?
}
}
You should define bytes as array with size of max message length not a pointer.
unsigned char byte, i;
unsigned char arr[10]; // 10 for example
i=0;
while (true){
byte = get();
arr[i] = byte;
i++;
if (byte == 'x'){
printf( "Your message: %s", arr);
}
}
When you define bytes as a pointer, it points to nothing and writing to it may erase other data in your program, you can make it array or allocate space for it in run time using malloc
Your Code
unsigned char byte;
unsigned char *bytes = NULL;
while (true){
Nothing wrong here, but some things must be cleared:
Did you alloc memory for your bytes buffer? That is, using malloc() family functions?
If so, did you check malloc() return and made sure the pointer is ok?
Did you include stdbool.h to use true and false?
Moving on...
byte = get();
bytes = byte;
*bytes++;
I'm assuming get() returns an unsigned char, since you didn't give the code.
Problem: bytes = byte. You're assigning an unsigned char to an unsigned char *. That's bad because unsigned char * is expecting a memory address (aka pointer) and you're giving it a character (which translates into a really bad memory address, cause you're giving addresses up to 255, which your program isn't allowed to access), and your compiler certainly complained about that assignment...
*byte++ has two "problems" (not being really problems): one, you don't need the * (dereferencing) operator to just increment the pointer reference, you could've done byte++; two, it was shorter and easier to understand if you switched this line and the previous one (bytes = byte) to *bytes++ = byte. If you don't know what this statement does, I suggest reading up on operator precedence and assignment operators.
Then we have...
if (byte == 'x'){
printf( "Your message: %s", bytes);
bytes = NULL;
}
if's alright.
printf() is messed up because you've been incrementing your bytes pointer the whole time while you were get()ting those characters. This means that the current location pointed by bytes is the end of your string (or message). To correct this, you can do one of two things: one, have a counter on the number of bytes read and then use that to decrement the bytes pointer and get the correct address; or two, use a secondary auxiliary pointer (which I prefer, cause it's easier to understand).
bytes = NULL. If you did malloc() for your bytes buffer, here you're destroying that reference, because you're making an assignment that effectively changes the address to which the pointer points to to NULL. Anyway, what you need to clear that buffer is memset(). Read more about it in the manual.
Another subtle (but serious) problem is the end of string character, which you forgot to put in that string altogether. Without it, printf() will start printing really weired things past your message until a Segmentation Fault or the like happens. To do that, you can use your already incremented bytes pointer and do *bytes = 0x0 or *bytes = '\0'. The NULL terminating byte is used in a string so that functions know where the string ends. Without it, it would be really hard to manipulate strings.
Code
unsigned char byte;
unsigned char *bytes = NULL;
unsigned char *bytes_aux;
bytes = malloc(500);
if (!bytes) return;
bytes_aux = bytes;
while (true) { /* could use while(1)... */
byte = get();
*bytes++ = byte;
if (byte == 'x') {
*(bytes - 1) = 0x0;
bytes = bytes_aux;
printf("Your message: %s\n", bytes);
memset(bytes, 0, 500);
}
}
if ((*bytes++ = get()) == 'x') is a compound version of the three byte = get(); *bytes++ = byte; if (byte == 'x'). Refer to that assignment link I told you about! This is a neat way of writing it and will make you look super cool at parties!
*(bytes - 1) = 0x0; The -1 bit is to exclude the x character which was saved in the string. With one step we exclude the x and set the NULL terminating byte.
bytes = bytes_aux; This restores bytes default state - now it correctly points to the beginning of the message.
memset(bytes, 0, 500) The function I told you about to reset your string.
Using memset is not necessary in this particular case. Every loop repetition we're saving characters from the beginning of the bytes buffer forward. Then, we set a NULL terminating byte and restore it's original position, effectively overwriting all other data. The NULL byte will take care of preventing printf() from printing whatever lies after the end of the current message. So the memset() part can be skipped and precious CPU time saved!
Somewhere when you get out of that loop (if you do), remember to free() the bytes pointer! You don't want that memory leaking...
I have written a program in C which will read the bytes at a specific memory address from its own address space.
it works like this:
first it reads a DWORD from a File.
then it uses this DWORD as a memory address and reads a byte from this memory address in the current process' address space.
Here is a summary of the code:
FILE *fp;
char buffer[4];
fp=fopen("input.txt","rb");
// buffer will store the DWORD read from the file
fread(buffer, 1, 4, fp);
printf("the memory address is: %x", *buffer);
// I have to do all these type castings so that it prints only the byte example:
// 0x8b instead of 0xffffff8b
printf("the byte at this memory address is: %x\n", (unsigned)(unsigned char)(*(*buffer)));
// And I perform comparisons this way
if((unsigned)(unsigned char)(*(*buffer)) == 0x8b)
{
// do something
}
While this program works, I wanted to know if there is another way to read the byte from a specific memory address and perform comparisons? Because each time, I need to write all the type castings.
Also, now when I try to write the byte to a file using the following syntax:
// fp2 is the file pointer for the output file
fwrite(fp2, 1, 1, (unsigned)(unsigned char)(*(*buffer)));
I get the warnings:
test.c(64) : warning C4047: 'function' : 'FILE *' differs in levels of indirectio
n from 'unsigned int'
test.c(64) : warning C4024: 'fwrite' : different types for formal and actual para
meter 4
thanks.
You can use the C language union construct to represent an alias for your type as shown
typedef union {
char char[4];
char *pointer;
} alias;
alias buffer;
This assumes a 32-bit architecture (you could adjust the 4 at compile time, but would then also need to change the fread() byte count).
Then, you can simply use *(buffer.pointer) to reference the contents of the memory location.
From your question, the application is not clear, and the technique seems error prone. How do you take into account the movement of addresses in memory as things change? There may be some point in using the linker maps to extract symbolic information for locations to avoid the absolute addresses.
Take note of the definition of fwrite,
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
which means that the warnings at the last part of your question are because you should be writing from a character pointer rather than writing the actual value of the character.
You can remove the extra type castings by assigning the pointer you read from the file to another variable of the correct type.
Examples to think about:
#include <stdio.h>
int main() {
union {
char buffer[8];
char *character;
long long number;
} indirect;
/* indirect is a single 8-byte variable that can be accessed
* as either a character array, a character pointer, or as
* an 8-byte integer! */
char *x = "hi";
long long y;
char *z;
printf("stored in the memory beginning at x: '%s'\n", x); /* 'hi' */
printf("bytes used to represent the pointer x: %ld\n", sizeof(x)); /* 8 */
printf("exact value (memory location) of (pointed to by) the pointer x: %p\n", x); /* 4006c8 */
y = (long long) x;
printf("%llx\n", y); /* 4006c8 */
z = (char *) y;
printf("%s\n", z); /* 'hi' */
/* the cool part--we can access the exact same 8 bytes of data
* in three different ways, as a 64-bit character pointer,
* as an 8-byte character buffer, or as
* an 8-byte integer */
indirect.character = z;
printf("%s\n", indirect.character); /* 'hi' */
printf("%s\n", indirect.buffer); /* binary garbage which is the raw pointer */
printf("%lld\n", indirect.number); /* 4196040 */
return 0;
}
By the way, reading arbitrary locations from memory seems concerning. (You say that you are reading from a specific memory address within the program's own address space, but how do you make sure of that?)
fp=fopen("input.txt","rb");
The file has an extension of .txt and you are trying to read it as a binary file. Please name files accordingly. If on Windows, name binary files with .bin extention. On Linux file extension do not matter.
// buffer will store the DWORD read from the file
fread(buffer, 1, 4, fp);
If you want to read 4 bytes, declare an unsinged int variable and read 4 bytes into it as shown below
fread(&uint, 1, 4, fp);
Why do you want to use a character array ? That is incorrect.
printf("the memory address is: %x", *buffer);
What are you trying to do here ? buffer is a pointer to a const char and the above statement prints the hex value of the first character in the array. The above statement is equal to
printf("the memory address is: %x", buffer[0]);
(*(*buffer)
How is this working ? Aren't there any compiler warnings and errors ? Is it Windows or Linux ? (*buffer) is a char and again de-referencing it should throw and error unless properly cast which I see you are not doing.
I'm working with TCP sockets. I'm sending data to the open socket using the write function.
write(Socket_Fd, "test", 4);
That works. But when I do it this way.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char BYTE;
typedef struct LANC
{
BYTE START;
BYTE END;
} LCODE;
int main(int argc, char *argv[]){
LCODE COMMAND;
COMMAND.START = 0x28;
COMMAND.END = 0x06;
short value = (COMMAND.START << 8) | COMMAND.END;
write(socket_FD, value, sizeof(value);
return 0;
}
when I check the size of the value I get 2 bytes which is correct since i combined 0x28 and 0x06. So doing a printf.
printf("%x\n", value);
output is: 2806 which is correct.
printf("%d\n", sizeof(value);
output is: 2 bytes which is correct.
I'm getting an error when I'm trying to write the hexadecimal to the open socket using write. What am I doing wrong?
You're committing two disgusting errors in one line (how does it even compile?). You're passing an integer (value) to write() where it expects a pointer (that won't compile, you're trying to deceive us about your code). Secondly, you're doing something that's endian-dependant, that is, on different processors you'll get different results depending on whether the high-byte of "value" comes first or second in memory.
Solution:
unsigned char value[2] = {COMMAND.START, COMMAND.END};
write(socket_FD, value, sizeof(value));