I want to make a function that converts unsigned char to unsigned int and store it into an array. However, this ends up with an error that says
passing argument 1 of 'sprintf' from incompatible pointer type.
int main(void) {
unsigned char key[16] = "1234567812345678";
phex(key, 16); //store into an array here
}
uint64_t* phex(unsigned char* string, long len)
{
uint64_t hex[len];
int count = 0;
for(int i = 0; i < len; ++i) {
count = i * 2;
sprintf(hex + count, "%.2x", string[i]);
}
for(int i = 0; i < 32; i++)
printf(hex[i]);
return hex;
}
As comments have already said, you have problems in your code...
First of all sprintf function does totally opposite thing of what you want/expect it to do. Next, you create a local variable in your function, and return pointer to it.. As soon as function exits, pointer is invalid. Third problem I see is that you never assign return value to anything...
Proposition on how to fix your code:
unsigned* phex(unsigned char* string, long len);
int main(void) {
int i;
unsigned char key[16] = "1234567812345678";
unsigned* ints = phex(key,16); //store into an array here
for(i = 0; i < 16; i++)
printf("%d ", ints[i]);
//never forget to deallocate memory
free(ints);
return 0;
}
unsigned* phex(unsigned char* string, long len)
{
int i;
//allocate memory for your array
unsigned* hex = (unsigned*)malloc(sizeof(unsigned) * len);
for(i = 0; i < len; ++i) {
//do char to int conversion on every element of char array
hex[i] = string[i] - '0';
}
//return integer array
return hex;
}
Related
I am trying to return an array from the function pointer, the code work but shows a warning in C that "incompatible pointer type". I want to return an array and it is already dynamic allocated. Can somebody tell me the problem and the solution to it
#include <stdlib.h>
#include<stdio.h>
unsigned short *reverse_seq(unsigned short num)
{
if(num==0) return NULL;
int size=num+1;
int* numbers=(int *) malloc(size*sizeof(int));
for(int i=0;i<num;i++){
numbers[i]=num-i;
}
for(int i=0;i<num;i++){
printf("%d ",numbers[i]);
}
return numbers;
}
int main(void)
{
int num=5;
reverse_seq(num);
return 0;
}
Can somebody give me the solution to this warning?
Your function is declared to return unsigned short * but you allocate space for ints and try to return an int*. I assume you want to store unsigned shorts in the allocated memory.
When you return a pointer to dynamically allocated memory, you should always assign that pointer to a variable so that you can free the allocated memory.
#include <stdio.h>
#include <stdlib.h>
unsigned short *reverse_seq(unsigned short num) {
if (num == 0) return NULL;
// corrected allocation (there's no need for num + 1 elements either):
unsigned short *numbers = malloc(num * sizeof *numbers);
if(numbers) { // check that allocation worked
for (int i = 0; i < num; i++) {
numbers[i] = num - i;
}
}
// printing moved to `main` to make use of the data there
return numbers;
}
int main(void) {
unsigned short num = 5; // same type as `reverse_seq` wants
unsigned short *numbers = reverse_seq(num);
if(numbers) { // again, check that allocation worked
for (int i = 0; i < num; i++) {
printf("%d ", numbers[i]);
}
free(numbers); // free the memory
}
}
If you want to return an array of unsigned short you should allocate an array of unsigned short but not of ints:
unsigned short* reverse_seq(unsigned short num)
{
if (num == 0)
return NULL;
unsigned short* numbers = malloc(num * sizeof(unsigned short));
if (numbers) {
for (unsigned short i = 0; i < num; i++) {
numbers[i] = num - i;
}
}
return numbers;
}
Try
#include <stdio.h>
#include <stdlib.h>
unsigned short *reverse_seq(unsigned short num) {
if (num == 0) return NULL;
int size = num + 1;
unsigned short *numbers = malloc((size_t) size * sizeof(unsigned short)); // THIS IS THE IMPORTANT CHANGE
for (int i = 0; i < num; i++) {
numbers[i] = (unsigned short) (num - i);
}
for (int i = 0; i < num; i++) {
printf("%d ", numbers[i]);
}
return numbers;
}
int main(void) {
int num = 5;
unsigned short *res = reverse_seq((unsigned short) num);
free(res);
return 0;
}
This will fix your major problem with the original warning.
The important thing is to allocate memory of the correct type of what you are returning. The problem is that you are returning a int* when a pointer to unsigned short* is requested. Not doing this
has consequences for accessing the memory later on since the memory layout of the access from the returned pointer does not match how you allocated your memory sequence.
You are allocating an array of integers, but you are returning an array of shorts (which normally are half the size of an integer). Just return a pointer to int, as in:
int *reverse_seq(unsigned short num) {
/* ... */
or allocate an array of shorts, as in:
unsigned short *numbers = malloc(num * sizeof *numbers); /* and please, ***never*** cast the result of malloc() */
I've written this function to remove count members from arr at index idx.
void remove_int(int (*arr)[], int idx, int count)
{
int i, j;
for (i = 0; i < count; i++)
for (j = idx; (*arr)[j]; j++)
(*arr)[j] = (*arr)[j+1];
}
I call it like this:
remove_int(&arr, index, cnt);
This works perfectly for local integers. Here's my problem. I have a header file like this:
struct {
/* other stuff */
char *array[100];
} global_struct;
Members in array are allocated and filled.
Someone figured I could just switch int to char and int (*arr)[] to char *(*arr)[], then call:
remove_char(&global_struct.array, index, cnt);
I tried it, but it doesn't actually modify global_struct.array. How should I change remove_int to work with global_struct.array?
global_struct.array is a pointer to char, and looks like it is intended to point to a string. So you need to change the function signature to something like:
void remove_strings(char *str[], size_t idx, size_t count);
I would suggest changing idx, count, i, and j to type size_t, as this is an unsigned integer type guaranteed to hold any array index. The size_t type has been available since C99.
Here is a demonstration program that incorporates a modified version of the remove_int() function:
#include <stdio.h>
struct {
char *array[100];
} global_struct;
void remove_strings(char *str[], size_t idx, size_t count);
int main(void)
{
global_struct.array[0] = "One";
global_struct.array[1] = "Two";
global_struct.array[2] = "Three";
global_struct.array[3] = "Four";
global_struct.array[4] = "Five";
global_struct.array[5] = NULL;
for (size_t i = 0; global_struct.array[i]; i++) {
printf("%s\n", global_struct.array[i]);
}
remove_strings(global_struct.array, 2, 2);
putchar('\n');
puts("After removal:");
for (size_t i = 0; global_struct.array[i]; i++) {
printf("%s\n", global_struct.array[i]);
}
return 0;
}
void remove_strings(char *str[], size_t idx, size_t count)
{
size_t i, j;
for (i = 0; i < count; i++)
for (j = idx; str[j]; j++)
str[j] = str[j+1];
}
Program output:
One
Two
Three
Four
Five
After removal:
One
Two
Five
Also, it appears that your function remove_int() only works on arrays of int that exclude 0 members, as 0 is used as a sentinel value in the inner loop of your function. It is common to terminate an array of pointers to char with a NULL pointer, as I have done, and of course a string is an array of chars terminated with a '\0'. But, it is not in general a good idea to terminate an array of ints with a zero. This feature of your code did make it a simple matter to adapt it to work with strings.
While your function may satisfy your current requirements, consider changing it to return the number of ints stored in the array. It makes sense to keep track of the number of ints stored in the array, and passing this value as an argument allows the function to iterate over the array without a sentinel value. Here is a revised version of your function:
size_t remove_ints(size_t idx, size_t count, int arr[], size_t arr_sz)
{
size_t i, j;
for (i = 0; i < count; i++)
for (j = idx; j < arr_sz; j++)
arr[j] = arr[j+1];
return arr_sz - count;
}
The purpose of "for (i = 0; i < count; i++)"?
As my understand I think you should:
void remove_int(int (*arr)[], int idx)
{
int j;
for (j = idx; (*arr)[j]; j++)
(*arr)[j] = (*arr)[j+1];
}
I'm learning how numbers are represented in memory. I want to know how to print the actual representation (binary or hexadecimal) in memory of some int and float variables.
I'd like to see what happens with that numbers when adding or subtracting it causes overflow, for example.
How can I access memory and print it?
You would need to assign a pointer to the variable in question to a char *, and treat it as an array of bytes of length sizeof(variable). Then you can print each byte in hex using the %X format specifier to printf.
You can define a function like this:
void print_bytes(void *ptr, int size)
{
unsigned char *p = ptr;
int i;
for (i=0; i<size; i++) {
printf("%02hhX ", p[i]);
}
printf("\n");
}
And call it like this:
int x = 123456;
double y = 3.14;
print_bytes(&x, sizeof(x));
print_bytes(&y, sizeof(y));
... to print the actual representation (binary ...
To convert any variable/object to a string that encodes the binary form uses a helper function that converts memory into a "binary" string. This method also handles function pointers. Uses C99 or later.
#include <stdio.h>
#include <assert.h>
#include <limits.h>
// .... compound literal .......
#define VAR_TO_STR_BIN(x) obj_to_bin((char [sizeof(x)*CHAR_BIT + 1]){""}, &(x), sizeof (x))
char *obj_to_bin(char *dest, void *object, size_t osize) {
const unsigned char *p = (const unsigned char *) object;
p += osize;
char *s = dest;
while (osize-- > 0) {
p--;
unsigned i = CHAR_BIT;
while (i-- > 0) {
*s++ = ((*p >> i) & 1) + '0';
}
}
*s = '\0';
return dest;
}
int main(void) {
int i = 42;
double d = 3.1415926535897932384626433832795;
printf("Sample\ndouble pi:%s\nint 42:%s\n", VAR_TO_STR_BIN(d), VAR_TO_STR_BIN(i) );
return 0;
}
Output (Note: depending in endian-ness, results may vary)
Sample
double pi:0100000000001001001000011111101101010100010001000010110100011000
int 42:00000000000000000000000000101010
This approach is easy to adapt to hexadecimal form.
Let's say you have a int variable called memory. Make sure you see how many bits it is; for many processors an int is 32 bits as well as a memory address. So you need to loop through each bit, like this:
unsigned int memory = 1234;
for (int i = 0; i < 32; i++)
{
printf("%d ", memory >> i & 1);
}
This simple method ORs each bit with 1 and shifts each bit by 1.
#include <stdio.h>
#include <stdlib.h>
void print_bits ( void* buf, size_t size_in_bytes )
{
char* ptr = (char*)buf;
for (size_t i = 0; i < size_in_bytes; i++) {
for (short j = 7; j >= 0; j--) {
printf("%d", (ptr[i] >> j) & 1);
}
printf(" ");
}
printf("\n");
}
int main ( void )
{
size_t n;
scanf("%d", &n);
print_bits(&n, sizeof(n));
return 0;
}
This prints bits of the specified object (n here) with the specified size (in bytes).
#dbush, #Anton, I mixed your codes. It's okay?
#include <stdio.h>
#include <stdlib.h>
void print_bytes( void *ptr, size_t size ) ;
int main( void )
{
int x = 123456 ;
double y = 3.14 ;
print_bytes( &x, sizeof(x) ) ;
print_bytes( &y, sizeof(y) ) ;
return 0 ;
}
void print_bytes( void *ptr, size_t size )
{
//char *buf = (char*) ptr;
unsigned char *p = ptr ;
for( size_t i = 0; i < size; i++ )
{
printf( "%02hhX ", p[i] ) ;
}
printf( "\n" ) ;
for( size_t i = 0; i < size; i++ )
{
for( short j = 7; j >= 0; j-- )
{
printf( "%d", ( p[i] >> j ) & 1 ) ;
}
printf(" ");
}
printf("\n");
}
Call print_bits(memory address of variable, size of variable in byte).
void print_bits(void *ptr, int size) //ptr = memory address of variable, size = size of variable in byte
{
long long *ch = ptr;
int size_bits = size * 8;
for(int i = size_bits-1; i>=0; i--){
printf("%lld", *ch >> i & 1) ;
}
}
It has been tested successfully, working with any variable of less than or equal to 64 bits. This will probably work correctly with variables with other sizes (Not Tested).
Calling:
double d = -7.92282286274e+28;
print_bits(&d, sizeof(d));
Output:
1100010111110000000000000000000011100000000000000000000100010111
I find this hard to explain but I'll do my best. I am passing an array to a function. I want to be able to grab the pointer of the array in the function and put the values of the array back into an array in the function.
If that doesn't make sense maybe this code will give you an idea of what I'm trying to attempt.
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH] = {*filter, *(filter+1), *(filter+2)};
}
int main() {
short filter[LENGTH] = {1,2,5};
FIR(filter);
}
This code works but is quite ridiculous if the filter length is long. How could I do this for any length of filter array? Keep in my mind, I'm trying to preserve efficiency.
Use a loop, *(filter+x) is equivalent to filter[x]
#include <stdio.h>
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH];
int i;
for(i = 0; i < LENGTH; ++i){
temp[i] = filter[i];
}
}
int main() {
short filter[LENGTH] = {1,2,5};
FIR(filter);
int i;
for(i = 0; i < LENGTH; ++i){
printf("%d ", filter[i]);
}
}
You can make your code look good by using loops or just use memcpy() to copy the whole array.
void FIR(short *filter)
{
short temp[LENGTH];
int i=0;
for(i=0;i<LENGTH;i++)
temp[i] = filter[i];
// or memcpy(temp,filter,sizeof(short) * LENGTH);
}
Since you talk about efficiency then go for the latter approach i.e. memcpy()
The most efficient approach is likely a memcpy. Since you know the type and size of the array.
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH];
memcpy(temp, filter, sizeof(short)*LENGTH)
}
You could use memcpy(), or you could initialize your local array in a loop. For example,
void FIR(short *filter) {
short temp[LENGTH];
memcpy(temp, filter, LENGTH * sizeof(short));
}
or
void FIR(short *filter) {
short temp[LENGTH];
int i;
for (i = 0; i < LENGTH; i += 1) {
temp[i] = filter[i];
}
}
Other than memcopy(), one way is by using pointers:
void FIR(short *filter)
{
short temp[LENGTH], *tempP;
int i = 0;
tempP = temp;
while(LENGTH > i++) *tempP++ = *filter++;
}
If you want the length to be variable then use this
#include <stdio.h>
void FIR(short *filter, int length) {
short *temp = new short[length];
int i;
for(i = 0; i < length; ++i){
temp[i] = filter[i];
}
}
int main() {
short filter[3] = {1,2,5};
FIR(filter, 3);
int i;
for(i = 0; i < 3; ++i){
printf("%d ", filter[i]);
}
}
I need a logic to acheive my target. I've buffer array size of 38400. This array data can be filled by a controller. Here i have to obtain an AES algorithm. In that i've to read 16 bytes of data from the buffer then encrypt, upto end of buffer. How to spilt an array into 16 bytes and encrypt? . I used following logic but i can't get it right now ?
unsigned char ptext[16] = "Attack at dawn!";
unsigned char ctext[16];
unsigned char decptext[16];
unsigned char buffer[120*160*2];
for (int count = 0; count < 120*160*2; count ++)
buffer[count] = count + 1;
for (i = 0; i < 120*160*2; i ++)
{
ptext[i]= buffer[i];
if(i%15 == 0)
{
aes_encrypt(ctx, ptext, ctext);
for(k = 0; k<=i; k++)
{
ptext[k]='\0';
}
}
}
void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
{
int i;
// copy input to state
for(i = 0; i < 16; i++)
ctx->state[i & 0x03][i >> 2] = input[i];
aes_addroundkey(ctx, 0);
for(i = 1; i < ctx->rounds; i++) {
aes_subbytes(ctx);
aes_shiftrows(ctx);
aes_mixcolumns(ctx);
aes_addroundkey(ctx, i);
}
aes_subbytes(ctx);
aes_shiftrows(ctx);
aes_addroundkey(ctx, ctx->rounds);
// copy state to output
for(i = 0; i < 16; i++)
{
output[i] = ctx->state[i & 0x03][i >> 2];
printf("%c",output[i]);
}
}
Note: I've filled buffer[] with random numbers.
Me only have to know how to split an array.
Thanks in Advance.
You don't need to "split" the array (whatever "split" means for you.) Just operate on every 16-byte segment of it:
void process_segment(unsigned char segment[])
{
// Work on the first 16 bytes of 'segment'.
}
// ...
unsigned char buffer[120*160*2];
for (size_t i = 0; i < 120*160*2; i += 16) {
process_segment(buffer + i);
}
The above is just an example. If you want a nested for loop instead, you'd do something like this:
unsigned char buffer[120*160*2];
for (size_t i = 0; i < 120*160*2; i += 16) {
unsigned char* segment = buffer + i;
// Work on the first 16 bytes of 'segment'.
for (size_t j = 0; j < 16; ++j) {
// Work on segment[j].
}
}
You should probably change your aes_encrypt() function to take an unsigned char input[] instead of an unsigned char input[16] so that you can pass segment to it.
The code you posted would then become something like this:
unsigned char ptext[16] = "Attack at dawn!";
unsigned char ctext[16];
unsigned char decptext[16];
unsigned char buffer[120*160*2];
for (int count = 0; count < 120*160*2; count++)
buffer[count] = count + 1;
for (i = 0; i < 120*160*2; i += 16) {
unsigned char *segment = buffer + i;
aes_encrypt(ctx, segment, ctext);
// Clear the current 16-byte segment.
memset(segment, '\0', 16);
// ctext now contains the encrypted data of the current
// 16-byte segment. I assume you want to save it somewhere
// now since it will be overridden in the next iteration of
// the loop.
}
And the signature of your aes_encrypt() function would become:
void aes_encrypt(aes_ctx_t *ctx, unsigned char input[],
unsigned char output[16])