I am trying to implement a unit cache structure and use calloc method(dynamic allocation) to give it memory space. I used the type-defined cache_unit as the type of the pointer to receive casted return type from calloc. Normally after calloc, all the bits in the allocated area should be 0. However my output is like random numbers instead of 0 and there're two warning messages.
Here's my code:
#include<stdio.h>
#include<stdlib.h>
#include <cstdint>
int main() {
typedef struct {
bool enabled;
uint8_t block[10];
int access_time;
} cache_unit;
cache_unit* cache = (cache_unit*) calloc(2, sizeof(cache_unit));
printf("%x ", *cache);
return 0;
}
Here are the warning messages on printf:
With printf("%x ", *cache);, "%x" expects a matching unsigned, not a cache_unit.
Try
printf("%d\n", cache->access_time);
Related
Below is the program:
#include <stdio.h>
#include<stdlib.h>
int *glob_var;
int* copy(void *a,int size)
{
int *t=(int *)calloc(1,sizeof(int));
int i;
int *glob_var=(int *)calloc(size,sizeof(int));
printf("glob_var=%p\n",glob_var);
printf("a=%p\n",a);
t=glob_var;
for(i=0;i<size;i++)
{
*glob_var=*(int *)a;
glob_var++;
(int *)a++;
// printf("a=%p\n",a);
}
glob_var=t;
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
glob_var=t;
printf("\n%p\n",glob_var);
return t;
}
int main() {
// Write C code here
int a=0x123456,i;
int *var=(int *)calloc(10,sizeof(int));
int *temp;
temp=var;
for(i=0;i<10;i++)
{
*var=i;
var++;
}
var=temp;
for(i=0;i<10;i++)
{
printf("%d\n",*var);
var++;
}
var=temp;
printf("var=%p\n",var);
glob_var=copy(var,10);
printf("%p\n",glob_var);
for(i=0;i<10;i++)
{
printf("%d\t",*glob_var);
glob_var++;
}
return 0;
}
However, the output I got is :
0 16777216 65536 256 1 33554432 131072 512 2 50331648
I was expecting: 0 1 2 3 4 5 6 7 8 9.
But, in the copy() function, if I replace (int *)a++; with a=(int *)a+1; it is working.
My question is: What is wrong with the current program?
Arithmetic on a pointer-to-void (void*) is not allowed in C1 and your compiler should warn you about that (at the very least) in the following line:
(int *)a++;
When I compile your code (using the clang-cl compiler in Visual Studio), I do, indeed, get two warnings for that line:
warning : arithmetic on a pointer to void is a GNU extension [-Wpointer-arith]
warning : expression result unused [-Wunused-value]
The first of these addresses the issue mentioned in my opening line (and discussed in the footnote) but it is the second that should be ringing alarm bells. That shows that the cast isn't working as intended – it is actually applied to the result of the a++ operation, because the cast has lower precedence than the post-increment.
However, when you use a = (int *)a + 1;, then all is working as intended, because the a pointer is cast to an int* before the arithmetic is performed (and then implicitly cast back to a void* for the assignment).
(There are other issues in your code, like the re-declaration of glob_var in your function, and the use of non-void pointers as arguments for the %p format specifier in several printf calls – but these are not really related to your reported problem. Also, this is worth a read: Do I cast the result of malloc?)
1 Some C compilers, such as GCC, do allow arithmetic on void* pointers, but I do not know what the 'base unit size' is for such operations. One would have to read the GCC manual to determine that, but it may very well by just 1, rather than the sizeof(int) required for your program, as presented, to work. Indeed, if that assumption is correct, and sizeof(int) is 4 on your platform, it would explain the three "garbage values" between successive 'real' data in your output.
I got some strange behavior of my code.
I can`t pass a structure to the callback function.
#include <malloc.h>
#include "stdint.h"
typedef struct {
int test_rssi;
int setup_rssi;
} test_setup_scan_result;
typedef void (*WifiCallback)(uint8_t);
WifiCallback TestSetupCb;
void resume_configuration(test_setup_scan_result *result) {
if (result == NULL) {
printf("result is NULL\n");
return;
}
printf("result is not NULL\n");
printf("setup_rssi %d\n", result->setup_rssi);
printf("test_rssi %d\n", result->test_rssi);
printf("done");
}
void scan_test_setup_done_cb() {
printf("scan_done\n");
test_setup_scan_result *scan_result = malloc(sizeof(test_setup_scan_result));
printf("created structure\n");
scan_result->test_rssi = 1;
scan_result->setup_rssi = 1;
printf("filled structure\n");
if (TestSetupCb) {
printf("executing cb\n");
printf("setup_rssi %d\n", scan_result->setup_rssi);
printf("test_rssi %d\n", scan_result->test_rssi);
TestSetupCb((uint8_t) scan_result);
}
}
void scan_for_test_setup(WifiCallback cb) {
TestSetupCb = cb;
scan_test_setup_done_cb();
}
int main(void) {
printf("Hello World\n");
scan_for_test_setup((WifiCallback)resume_configuration);
return 0;
}
The code after I am trying to get values of the structure in resume_configuration function just not works. I am the newbie in c language so any links to useful articles are regarded.
Casting a function name to a function pointer type with incompatible parameter types is undefined behavior:
scan_for_test_setup((WifiCallback)resume_configuration);
// ^^^^^^^^^^^^^^
// Undefined behavior
This by itself is enough to get a crash. However, your program does another thing illegally - the call below
TestSetupCb((uint8_t) scan_result);
// ^^^^^^^^^^^
// Does not fit in uint8_t
would fail regardless of the function pointer cast, because a pointer does not fit in 8 bits.
The variable “scan_result” is pointer to struct with allocated memory space in heap region.
When the TestSetupCb() is called with argument “(uint8_t) scan_result” you actually casting address of “scan_result” to be uint8_t, which means to take a first byte of the address and pass it by value. In that case you lose data that you want process in resume_configuration() function.
For example: let’s say the “scan_result” struct it at address “0x004EE388” when you casting this address to uint8_t the result is “0x00000088” this address is invalid and creates issue in your program. Also, this kind of operation creates dangerous to your program.
To solve your problem just re-define function pointer in the following way:
typedef void(*WifiCallback)( test_setup_scan_result *);
and update your code: instead of TestSetupCb((uint8_t)scan_result); change to TestSetupCb(scan_result);
I have run it in Valgrind and I have identified a blatant error (which manifests in several places):
resume_configuration does not obey the WifiCallback pointer type; it takes a parameter of pointer type, not of uint8_t type which most likely has a different size (and it indeed has)
You call TestSetupCb((uint8_t) scan_result); -- you explicitly convert the scan_result pointer to a datatype smaller than a pointer. You have truncated a pointer, so now the result cannot be converted back into a valid pointer. The truncation on Intel systems is so bad, any resulting pointer will always be in the NULL page.
As far as I've understood this far array[1] and array+1 are practically two ways of writing the same thing. However I've been looking at void pointers and arrays recently and made this program to test my understanding of it.
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data) = 5;
*((int*)(data+1)) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)(data+1)));
free(data);
return 0;
}
That is the version of the program that works, for some reason however this version doesn't
#include <stdio.h>
#include <stdlib.h>
int main(void){
void** data;
data = malloc(sizeof(int)*2);
*((int*)data[0]) = 5;
*((int*)data[1]) = 10;
printf("%d\n", *((int*)data));
printf("%d\n", *((int*)data1]));
free(data);
return 0;
}
I'm not exactly getting compiler errors but program simply stops running, I've compiled this on a win 10 machine using gcc with the following flags -pedantic-errors -Wall and like i said before, the program compiles but when run I get the classic Program.exe has stopped working error message and so far I really can't think of a single reason why one of those would work and the other wouldn't.
data+1 is not valid C. You cannot do pointer arithmetic on void pointers, since that wouldn't make any sense.
So it would seem that you are using gcc in non-standard crap mode (default setting), which translates void pointer arithmetic to character arithmetic and therefore the program compiles, but as non-standard C. data+1 would then mean +1 byte, not +1 int.
Use gcc as a a standard C compiler instead -std=c11 -pedantic-errors. Then change the code to (int*)data+1.
Also the void** makes no sense, should be a void*. Please note that (int*)data[0] means "do pointer arithmetic on void** type, then cast the result to int*. This is an operator precedence bug. [] has higher precedence than the cast () operator.
Just toss that whole code out and use this:
#include <stdio.h>
#include <stdlib.h>
int main(void){
void* data;
data = malloc( sizeof(int[2]) );
((int*)data)[0] = 5;
((int*)data)[1] = 10;
printf("%d\n", *(int*)data );
printf("%d\n", *((int*)data+1) );
free(data);
return 0;
}
Both your examples are not correct.
void** data = malloc(sizeof(int)*2);
is allocating 2 int integers, but data if of type void**.If you wish to still use this, which is not recommended, you need to allocate 2 void* pointers. This would then be:
void** data = malloc(sizeof(void*)*2);
Having said this, using void** is not needed here. You can just use void* as pointed out in #Lundin's post. Your code would be optimal if you use int *data instead though, as it doesn't really make sense to use void* pointers here. If you decide to do this, your code can just be:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *data;
data = malloc(sizeof(int)*2);
data[0] = 5;
data[1] = 10;
printf("%d\n", data[0]);
printf("%d\n", data[1]);
free(data);
return 0;
}
Which is more straightforward, and skips the complications that void* pointers bring in code.
Note: You must check return of malloc() always, as it can return NULL on failure.
first: please change the type of data to int* or at least to void*.
don't mess with void** unless you need to pass to a function a pointer.
second: change data[0/1] to &data[0/1].data[] is an argument and &data[] is his pointer. if you still using the void* choose *((int*)data+?). if yopu changed to int* use data[?].
third: why to use pointers in this function? this is not a function that need pointers.
fourth: i would suggest in this case to use an array instead of the pointers. if you already know the type and size of your argument so you better use arrays. more comfortable.
I am attempting to create a function in C that is called from Fortran. First things first. The fortran code is being compiled with f77, and the c is compiled with gcc. Both are compiled into .so libraries. The c function is going to read the memory on a device at an address, and size, specified by the fortran. I am able to see the address, and size being passed to the c, but I am having trouble filling the data in the c function and returning it to the fortran. See the relevant code below. My assumption is that there is something wrong in the memory allocation or pointer syntax for the data variable.
C
void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{
int i;
printf("addr %x \n", *addr);
printf("size %i \n", *size);
for ( i = 0; i<*size; i++)
{
*data[i] = i;
printf("memory %i \n",*data[i]);
}
}
Fortran
integer memory(4)
call copymemory(z'dead', 4, memory)
DO i = 1,memsize
call printf(memory(i))
END DO
I have several points to your code.
Please, supply compilable code and describe the output of that exact code!
That includes the #include for standard headers, if you want people to debug your code, make it easy for them so that they don't have to search which lines did you omit because they seemed "obvious" to you. Just paste everything. The code should compile when copied from here!
Even the executable part of your code does not compile in my compiler. I had to change the *data to data. Are you sure you copied your actual code?
cfun.c: In function ‘copymemory_’:
cfun.c:13:9: error: invalid type argument of unary ‘*’ (have ‘int’)
*data[i] = i;
^
cfun.c:14:31: error: invalid type argument of unary ‘*’ (have ‘int’)
printf("memory %i \n",*data[i]);
^
Your Fortran code contains a call to some printf subroutine. Where is this defined? Is it present in your actual code? I doubt so. Please copy to StackOverflow always a complete and compilable code.
So after fixing the obvious your present code is:
#include <stdio.h>
#include <stdint.h>
void copymemory_( uint32_t *addr, int *size, uint8_t *data )
{
int i;
printf("addr %x \n", *addr);
printf("size %i \n", *size);
for ( i = 0; i<*size; i++)
{
data[i] = i;
printf("memory %i \n",data[i]);
}
}
implicit none
integer :: memsize = 4
integer memory(4)
integer i
call copymemory(z'dead', 4, memory)
DO i = 1,memsize
print *, (memory(i))
END DO
END
It does not crash but memory in Fortran contains garbage. It has to, because it is integer and you are treating it as int8_t in C.
So either treat it as an array of four integers in C or copy it byte by byte, but then you must pass the correct number of bytes to copy. From your description it is not clear which one is your intention so I will show just one possibility:
void copymemory_( uint32_t *addr, int *size, uint32_t *data )
The output is correct then:
> gfortran-4.10 -fsanitize=address cfun.c ffun.f90
> ./a.out
addr dead
size 4
memory 0
memory 1
memory 2
memory 3
0
1
2
3
This is the first code:
#include <stdio.h>
#include <stdlib.h>
void test(int,int);
int main()
{
int p=23,f=24;
test(&p,&f);
printf("%d %d\n",p,f);
return 0;
}
void test(int q,int g)
{
q=q+q;
g=g+g;
}
This code generates TYPE MISMATCH ERROR maybe due to the fact that I have passed address of variable as argument during function calling and the formal parameters are not pointers.
This is the second code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int p=23,f=24,q,g;
q=&p;
g=&f;
printf("%d %d\n",q,g);
return 0;
}
The output of second code is
1638220 1638228
In this code, q and g are not pointers. So why are they giving correct output, not the error?
Note:
Your comment: "The second code prints the correct addresses of p and f where as first code gives error" is wrong on various levels.
You claim your printf statement prints the memory addresses of the variables? Wrong, it does no such thing. Can't. Impossible. Not going to happen.
To print the memory addresses of variables, a printf statement should look like this:
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);//one of few cases where you SHOULD cast
You're printing just a number:
printf("%d %d", p, f);
Those are not the same thing. Just take a look at the example at the bottom of this answer, but read the bit in the middle, too
Well, you declared q and g as ints, and assigned them the memory addresses of p and f. It's undefined behaviour (ie the standard doesn't determine what to do with this, so it may vary depending on the compiler, WCS: your application crashes). In your case, I'd say this happens:
Basically, a memory address looks something like this:
0x213ABC
A hexadecimal value, which can be interpreted as a number, so there's nothing stopping your from assigning it to a char, or size_t or whatever.
HOWEVER, if you compile your code with -Wall, you should get a warning about the implicit conversion from type int * to int. Aside from that, you're "safe". Mind your: the program's output will be unpredictable and therefore rather pointless.
The first snippet contains a bigger problem: you're passing a value to a function that simply does not exist! The test function cannot handle what you're passing, because its prototype shows it expects 2 ints, not 2 pointers
test(&p,&f);
//to:
test((int) &p,(int) &f);
However, it does compile, as you can see here, however the results are unpredictable (undefined behaviour).
When calling test(&p, &f) you are calling a function that should look like this:
void test(int *, int *)
However, this signature/prototype is nowhere to be found, so the compiler can't continue. Casting the memory addresses to ints changes all that, and lets the compiler know that the function looks like void test (int, int), and that function does exist, hence it compiles.
Think of it like this:
You: What's your phone-number?
Me: abc
you: That's not a phone number
Me: I meant 1-11-111 (number keys for text messages, those were the days)
That's what you're doing here:
test(&p, &f);
//compiler: can't find function test(int *, int *)
//you: I expect you to call test(int, int), and implicitly cast the pointers to ints
That's not how C works.
Note:
As pointed out to me in the coments: Assigning/casting pointer to int is undefined behaviour (ie: the result of these actions are not defined by the standard)
The example program that prints pointers, and unsigned long and ints as they should be printed:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int p = 2, f = 4, q;
q = (int) &f;
printf("p # %p\nf # %p\n", (void *) &p, (void *) &f);
//int is too small for 64bit address, use unsigned long here
printf("%d != %ul != %p\n", q, &f, (void *) &f);
return EXIT_SUCCESS;
}
When I ran it through this codepad, I got the following output:
p # 0xbf70e1d8
f # 0xbf70e1d4
-1083121196 != 3211846100l != 0xbf70e1d4