I'm trying to hexdump a file with following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define SIZE 16
void pre_process(char buffer[],int len);
int main(int argc, char **argv){
if(argc == 2){
char *file = argv[1];
FILE *input = fopen(file,"r");
char buffer[SIZE];
char *tmp = malloc(4);
while(!feof(input)){
printf("%06X ",ftell(input)); /*print file pos*/
fread(buffer,1,SIZE,input); /*read 16 bytes with buffer*/
for (int i=0;i<SIZE;i += 4){ /*print each 4 bytes with hex in buffer*/
memcpy(tmp,buffer+i,4);
printf("%08X ",tmp);
}
printf("*");
pre_process(buffer,SIZE); /*print origin plain-text in buffer. subsitute unprint char with '*' */
printf("%s",buffer);
printf("*\n");
}
free(tmp);
fclose(input);
}
}
void pre_process(char buffer[],int len){
for (int i=0;i<len;i++){
if(isblank(buffer[i]) || !isprint(buffer[i]))
buffer[i] = '*';
}
}
reading a slice from lord of ring,result as below:
enter image description here
so, why the hex code are all the same ? It looks like something wrong with printf("%08X ",tmp);
thx for your help.
The answer lies here:
memcpy(tmp,buffer+i,4);
printf("%08X ",tmp);
memcpy as you might already be aware, copies 4 bytes from buffer+i to where tmp is pointing to.
Even though this is done in a loop, tmp continues to hold the address of a specific location, which is never changed. The contents at that address/location in memory are updated with every memcpy() call.
In a nutshell, the house remains there only, hence the address remains the same but people change places, new people arrive as older ones are wiped out!
Also, there is plenty to improve/fix here. I recommend starting with enabling warnings by -Wall option with your compiler.
tmp stores the address of a buffer; that address never changes. What you want to print is the contents of the buffer that tmp points to. In this case, tmp point to a buffer of 4 chars; if you write
printf( "%08X ", *tmp );
you’ll only print the value of the first element - since tmp has type char *, the expression *tmp has type char and is equivalent to writing tmp[0].
To treat what’s in those bytes as an unsigned int (which is what the %X conversion specifier expects), you need to cast the pointer to the correct type before dereferencing it:
printf( "%08X ", *(unsigned int *) tmp );
We first have to cast tmp from char * to unsigned int *, then dereference the result to get the unsigned int equivalent of those four bytes.
This assumes sizeof (unsigned int) == 4 on your system - to be safe, you should write your malloc call as
char *tmp = malloc( sizeof (unsigned int) );
and
for ( int i = 0; i < SIZE; i += sizeof (unsigned int) )
{
memcpy( tmp, buffer + i, sizeof (unsigned int) );
...
}
instead.
You should not use feof as your loop condition - it won’t return true until after you try to read past the end of the file, so your loop will execute once too often. You’ll want to look at the return value of fread to determine whether you’ve reached the end of the file.
Related
I am new to C and still trying to figure out pointer.
So here is a task I am stuck in: I would like to assign 10 fruit names to a pointer of array and print them out one by one. Below is my code;
#include <stdio.h>
#include <string.h>
int main(){
char *arr_of_ptrs[10];
char buffer[20];
int i;
for (i=0;i<10;i++){
printf("Please type in a fruit name:");
fgets(buffer,20,stdin);
arr_of_ptrs[i]= *buffer;
}
int j;
for (j=0;j<10;j++){
printf("%s",*(arr_of_ptrs+j));
}
}
However after execution this, it only shows me the last result for all 10 responses. I tried to consult similar questions others asked but no luck.
My understanding is that
1) pointer of array has been allocated memory with [10] so malloc() is not needed.
2) buffer stores the pointer to each individual answer therefore I dereference it and assign it to the arr_of_ptrs[i]
I am unsure if arr_of_ptrs[i] gets me a pointer or a value. I thought it is definitely a pointer but I deference it with * the code and assign it to *buffer, program would get stuck.
If someone could point out my problem that would be great.
Thanks in advance
Three erros, 1. You must allocate memory for elements of elements of arr_of_ptrs, now you only allocate the memory for elements of arr_of_ptrs on stack memory. 2. arr_of_ptrs[i]= *buffer; means all of the arr_of_ptrs elements are pointed to same memory address, which is the "buffer" pointer. So all the elements of arr_of_ptrs will be same to the last stdin input string. 3. subsequent fgets() call has potential problem, one of the explaination could be here
A quick fix could be,
#include <stdio.h>
#include <string.h>
int main(){
const int ARR_SIZE = 10, BUFFER_SIZE = 20;
char arr_of_ptrs[ARR_SIZE][BUFFER_SIZE];
char *pos;
int i, c;
for (i = 0; i < ARR_SIZE; ++i) {
printf ("Please type in a fruit name: ");
if (fgets (arr_of_ptrs[i], BUFFER_SIZE, stdin) == NULL) return -1;
if ((pos = strchr(arr_of_ptrs[i], '\n')))
*pos = 0;
else
while ((c = getchar()) != '\n' && c != EOF) {}
}
for (i = 0; i < ARR_SIZE; ++i)
printf("%s\n", arr_of_ptrs[i]);
return 0;
}
The misunderstanding is probably that "Dereferencing" an array of characters, unlike dereferencing a pointer to a primitive data type, does not create a copy of that array. Arrays cannot be copied using assignment operator =; There a separate functions for copying arrays (especially for 0-terminated arrays of char aka c-strings, and for allocating memory needed for the copy):
Compare a pointer to a primitive data type like int:
int x = 10;
int *ptr_x = &x;
int copy_of_x = *ptr_x; // dereferences a pointer to x, yielding the integer value 10
However:
char x[20] = "some text"; // array of characters, not a single character!
char *ptr_x = &x[0]; // pointer to the first element of x
char copy_of_first_char_of_x = *ptr_x; // copies the 's', not the entire string
Use:
char x[20] = "some text";
char *ptr_x = &x[0];
char *copy_of_x = malloc(strlen(ptr_x)+1); // allocate memory large enough to store the copy
strcpy(copy_of_x,ptr_x); // copy the string.
printf("%s",copy_of_x);
Output:
some text
In the main function, I use malloc() to create an unsigned char array:
int main()
{
int length = 64;
unsigned char *array = (unsigned char *)malloc(length * sizeof(unsigned char));
...
change_size(array, length);
}
change_size() defined in .h:
void change_size(unsigned char* arr, int len);
In the change_size function, I will use realloc() to increase the array size:
void change size(unsigned char* arr, int len)
{
printf("%d\n", len);
len = len + 16;
printf("%d\n", len);
arr = (unsigned char *)realloc(arr, len * sizeof(unsigned char));
int new_len = sizeof(arr)/sizeof(arr[0]);
printf("%d\n", new_len);
}
The printf() show me:
64
80
8
The array size in the main() also needs to be updated.
Then how to change this array size correctly?
You need to pass your parameters as pointers if you want to change their value back in the caller. That also means you pass your array pointer as a pointer, because realloc might change it:
int change_size(unsigned char **arr, int *len)
{
int new_len = *len + 16;
unsigned char *new_arr = realloc(*arr, new_len);
if (new_arr) {
*len = new_len;
*arr = new_arr;
}
return new_arr != NULL;
}
Here I've modified change_size to suit, and also added a return value to indicate success, since realloc can fail to resize the memory. For clarity, I removed the printf calls. Oh, and I also removed the cast, since that is not valid in C.
Example usage:
if (!change_size(&array, &len))
{
perror("change_size failed");
}
One final note is that you can use your change_size function for the first allocation too, rather than calling malloc. If the first argument to realloc is NULL, it does the same thing as malloc.
First C is not babysitter language,
You only need basic things then you can do everything,
Just try hard to totally understand basic.
#include <stdio.h>
#include <stdlib.h>
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
free(G1);
return 0;
}
Okay I answer it. #Chipster
#include <stdio.h>
#include <stdlib.h>
int change_size(char** arr, int len)
{
char* nar=(char*)malloc(sizeof(char)*(len+16));
if(nar){
free(* arr);
*arr=nar;
nar[10]='K';//this will let you know its right
return len+16;
}
return len;
}
int main(){
int G1_Len=20;
int G2_Len=40;
char* G1=(char*)malloc(sizeof(char)*G1_Len);
char* G2=(char*)malloc(sizeof(char)*G2_Len);
printf("This is G1's Size:%d,Becuz G1 is Pointer\n",sizeof(G1));
printf("%d\n",sizeof(G2));
printf("This is what you need just add a variable remainber your size\n%d\n",G1_Len);
printf("%d\n",G2_Len);
/*alloc and free is a pair of memory control you need,remember least function thinking more is tip of C*/
/*if you need alot of function but you cant control all try c++*/
/*and if in c++ using new and delete dont use malloc free*/
free(G1);
free(G2);
G1=NULL;
G2=NULL;
G1_Len=22;
G1=(char*)malloc(sizeof(char)*G1_Len);
//Now you have 22 bytes of char array
printf("%d\n",G1);
G1_Len=change_size(&G1,G1_Len);
printf("%c\n",G1[10]);
printf("%d\n",G1);
printf("%d\n",G1_Len);
free(G1);
return 0;
}
I was trying to store an int value (all 4 bytes) into a char *:
So, I would like to store the full value i.e all the bytes (all 4) of the int variable into the char such that I use up 4 bytes out of the 512 bytes. I should also be able to read back the value that I assigned. I tried to use a lot of the stuff but couldn't figure this out.
This is for my LFS (Log File System) where I try to store files into data blocks on my disk using fragmentation of data
char *c = malloc(512);
int value = 4096;
You can copy into the buffer pointed to by c:
memcpy(c, &value, sizeof(value));
If you want to write another value following that, you can add offset to c:
memcpy(c + sizeof(value), &value2, sizeof(value2)); // adds value2 at an offset right after value
To read the value, you can copy it into a different variable:
int readVal;
memcpy(&readVal, c, sizeof(readVal));
It's been a while since I've written C or C++, but I believe you can use memcpy to do what you desire.
memcpy(c, &value, 4);
This should copy 4 bytes from the address of value into the bytes you allocated from c. If you wanted to be sure about the size of the integer, you could use sizeof(int) instead of 4. So that would be
memcpy(c, &value, sizeof(int));
Additional pointers could be used.
Cast the char pointer to make it available to an int pointer. The int pointer can be used as an array and can be easily assigned or printed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void) {
char *line = malloc ( 512);
char *text = line + sizeof ( int) * 2;//reserve space for two int
int *value = (int *)line;//cast to int pointer
value[0] = 4096;//or *value = 4096;
value[1] = 25;
strcpy ( text, "text and more text");
printf ( "%d\n", value[0]);//or printf ( "%d\n", *value);
printf ( "%d\n", value[1]);
printf ( "%s\n", text);
return 0;
}
One could use a union to write directly to the value,
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> /* C99 */
union Block {
char c[512];
int32_t d;
};
int main(void) {
union Block *b;
if(!(b = malloc(sizeof *b))) return perror("?"), EXIT_FAILURE;
b->d = 4096;
printf("%d\n", b->d);
return 0;
}
Here, I've used the C99 int32_t to ensure that it's 32 bits. However, the bit order (what is b->c[0]?) depends on if one is using little or big endian.
I have been looking on internet for this and so far i just found a lot of questions for specific answer and not a general one.
i am kind of rusty on C. And i want to make a function that will return an array of char.
this is what i got and is not working. basically a way to convert a byte array to an array of chars to do atoi later..
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *get_char(int my_byte[], int packetsize)
{
char *array_char=(char *) malloc(sizeof(char)*10); //trying this but didnt work
// char array_char[10]; //i had it like this before(was told to do it)
for(int i=0;i<10;i++)
{
array_char[i]=my_byte[i]+0;
}
return array_char;
}
int main()
{
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp;
char data;
temp=get_char(byte_array,10);
data=*temp;
printf("String point %s ",data);
}
Two fixes:
As you want to convert to char, then
array_char[i]=my_byte[i]+0; should be array_char[i]=my_byte[i]+'0'; Note '0' is character (that will be converted to int) instead of numeric 0 (which doesn't do anything).
Also you must free temp pointer in main as that memory is dynamically allocated in get_char() function.
Edit: just notice another issue in your get_char()
char *array_char=(char *) malloc(sizeof(char)*10);
should be
char *array_char= malloc(sizeof(char)*(packetsize+1));
After the for loop, ensure the buffer is NUL-terminated:
array_char[packetsize] = '\0';
Notice that your packetsize is never used - you should get some compiler warning about it. It's bad to hard code 10 in your malloc - it's actually the whole idea of parsing the packetsize as a parameter - so use it properly.
You need to watch out for these things:
You need to add a null-terminating character at the end of *array_char, otherwise using this pointer allocated from the heap will cause undefined behaviour.
You can simply allocate *array_char like this:
char *array_char = malloc(packetsize+1);
As sizeof(char) is 1, and +1 for trailing nullbyte.
You also don't need to cast return of malloc().
Instead of passing 10 as packetsize to get_char(), you should pass this size as sizeof(arr) / sizeof(arr[0], which is the calculated size of the array. This can be a size_t variable declared somewhere or even a macro.
malloc() needs to be checked, as it can return NULL if unsuccessful.
You need to free() temp at some point in the program.
array_char[i]=my_byte[i]+0; needs to be array_char[i]=my_byte[i]+'0'; instead, as '0' is the ascii code for a zero character.
char data needs to be char *data, as temp is a pointer.
If you compile with -Wall -Wextra, you will see that this line:
data=*temp;
Is dangerous, and will trigger warnings of making pointers from integers without a cast. It will most likely lead to a segmentation fault. If temp and data are both pointers, then you can simply use:
data=temp;
Which sets data to the address of temp. Sometimes this is written as data = &(*temp);, but this is harder to read. Although their is no need for data, and using temp alone should be fine.
Your code can then look like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
char *get_char(int my_byte[], size_t packetsize) {
char *array_char = malloc(packetsize+1);
const char ascii = '0';
size_t i;
if (!array_char) {
printf("Cannot allocate %zu bytes\n", packetsize+1);
exit(EXIT_FAILURE);
}
for(i = 0; i < packetsize; i++) {
array_char[i] = my_byte[i] + ascii;
}
array_char[i] = '\0'; /* or array_char[packetsize] = '\0' */
return array_char;
}
int main(void) {
int byte_array[]={1,2,3,4,5,6,7,8,9,0};
char *temp, *data;
temp = get_char(byte_array, ARRAYSIZE(byte_array));
data = temp;
printf("String point %s\n", data);
printf("String converted into number = %d\n", atoi(data));
free(temp);
temp = NULL;
return 0;
}
You can also look into strtol, which is better than using atoi() in terms of error checking.
It is Not Wise Idea to Return a Array From A Function. So how to return a string then? As most of libc functions use we can use some thing like that (i.e) passing a buffer along with our input and expect function to use output buffer to give us result.
Some issue to take care while coding
write your logic first.
try to use available functions from libc.
while dealing with byte data/binary data be take precaution of buffer overflow.
don't allocate in a function and de-allocate in another function.
Below is Example of your code with modification.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <stdint.h>
int get_char(uint8_t my_byte[], int packetsize, char *buffer, int max_buffer)
{
int byte_itr, buf_itr;
char temp_buf[16]={0x00};
for(byte_itr=0, buf_itr=0; byte_itr<packetsize && max_buffer > buf_itr; byte_itr++)
{
memset(temp_buf, 0x00, sizeof(temp_buf));
char temp_ch = my_byte[byte_itr];
snprintf(temp_buf, sizeof(temp_buf), "%d", temp_ch);
if( buf_itr+strlen(temp_buf) >=max_buffer){
break;
}else{
buf_itr += strlen(temp_buf);
strcat(buffer, temp_buf);
if(byte_itr+1 < packetsize){
strcat(buffer, ",");
buf_itr += 1;
}
}
}
return buf_itr;
}
int main()
{
uint8_t byte_array[]={1,2,3,4,5,6,7,8,9,0};
char char_array[32]={0x00};
int len = get_char(byte_array, 10, char_array, sizeof(char_array));
printf("String point %s : len %d\n", char_array, len);
}
NOTE:
when length return and size of output buffer same then buffer full condition happened.
I am having some memory issues with printing hex in the following format: \xAA\xAB\xDC using my encryption routine.
I did some modifications, using snprintf() and strcat() in an attempt to fix the output and it worked to some degree.
This is the function I originally started out with, which is probably better than my modified version.
char *encrypt(char key, const char *a) {
char *output = malloc(strlen(a)+1);
bzero(output, strlen(a)+1);
strcpy(output, a);
char *tmp = output;
int i;
for (i = 0; tmp[i] != 0; i++) {
tmp[i] = key ^ tmp[i];
}
return output;
}
My current progress is as follows:
char *encrypt(char key, const char *a)
{
char buf[256];
char *tmp = a;
int i;
int *k;
for (i = 0; tmp[i] != 0; i++)
{
char temp[10];
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
strcat(buf, temp);
}
return buf;
}
int main(int argc, char **argv)
{
if (argv[1] == NULL){
printf("Usage: %s <string>\n", argv[0]);
}
else printf("Encrypted string: %s\n", encrypt(0xEB, argv[1]));
return 0;
}
If anyone could point me in the right direction on how to fix the memory issue, and if the code can be improved I would appreciate that a lot.
The primary issue, in your code, buf is local to the function encrypt(). So you may not return the array from the function. Once the function finishes, the array will cease to exist and the returned address will be invalid. If the returned value is ued in the caller, it will invoke undefined behavior.
You need to define buf as a pointer and allocate dynamic memory using malloc() or family. Also, you need to free() the memory, once the usage is over.
That said,
you have defined k to be a pointer but did not allocate memory to it.
k = key ^ tmp[i]; seems meaningless, maybe you meant *k = key ^ tmp[i];
%s expects a pointer to char array (null-terminated) as argument. From that point, snprintf(temp, sizeof(temp), "\\x%s", k); also looks wrong. What you need is snprintf(temp, sizeof(temp), "\\x%d", *k); to print the int value.
Instead of:
int *k;
k = key ^ tmp[i];
snprintf(temp, sizeof(temp), "\\x%s", k);
use this:
unsigned char k;
k = key ^ tmp[i];
snprintf(temp, sizeof temp, "\\x%02X", k);
Note that you also have other changes to make regarding buf. Firstly you never initialize it, so you are appending to junk. And you never check that you didn't overflow it.
Also you attempt to return this from a function, however, since it is a local variable, it ceases to exist when the function returns.
See this thread for some suggestions of how to get freshly-written string out of a function. You could use malloc(256) in the same vein as your first attempt (and remember to replace sizeof buf with the mallocated length, in the snprintf call).
It'd be more robust to use unsigned char instead of char for both the key and the message. An example of the issues is that on x86 or x64, char has a range of -128 to 127 so when you supply 0xEB (i.e. 235) this is an out-of-range assignment which is not well-defined.
But on common systems you will get away with using char because they tend to define out-of-range assignment by using 2's complement and truncating excess bits, which works in your situation.