why first code give error and second does not? - c

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

Related

Failing to copy set of integers in main function to a dynamically allocated memory in copy() function

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.

how to pass a condition as parameter to function in C?

I have created an array of function pointers to swap two variables.
pointer pointing to these functions namely: swap1, swap2. swap3 and swap4.
swap2 is swaping using pointer passed as arguments.
but while declaring the function pointer, only int and int are passed as arguments. after compiling this causes many warnings.
so do we have a better way of passing the argument, where we put condition in function call itself.
code is given below.
#include <stdio.h>
int swap1(int ,int );
int swap2(int* ,int* );
int swap3(int ,int );
int swap4(int, int);
int swap1(int a,int b)
{
int temp=a;
a=b;
b=temp;
printf("swapped with 3rd variable :%d, %d\n", a,b);
}
int swap2(int *a,int *b)
{
int temp = *a;
*a = *b;
*b = temp;
printf("swapped with pointer :%d, %d\n", *a,*b);
}
int swap3(int a,int b)
{
a+=b;
b=a-b;
a-=b;
printf("swapped with 2 variable :%d, %d\n", a,b);
}
int swap4(int a,int b)
{
a=a^b;
b=a^b;
a=a^b;
printf("swapped with bitwise operation :%d, %d\n", a,b);
}
int main()
{
int ch;
int a=3;
int b=4;
printf("enter the option from 0 to 3\n");
scanf("%d",&ch);
int (*swap[4])(int, int) ={swap1,swap2,swap3,swap4};// function pointer
/*can we pass something like int(*swap[4]( condition statement for 'pointer to variable' or 'variable')*/
if (ch==1)// at '1' location, swap2 is called.
{
(*swap[ch])(&a,&b);//passing the addresses
}
else
{
(*swap[ch])(a,b);
}
return 0;
}
some warnings are as follows.
at line 36 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
WARNING: found pointer to int where int is expected
at line 47 in file '9e748221\script.c'
Well yes. There are a number of problems with your code, but I'll focus on the ones to which the warnings you presented pertain. You declare swap as an array of four pointers to functions that accept two int arguments and return an int:
int (*swap[4])(int, int)
Your function swap2() is not such a function, so a pointer to it is not of the correct type to be a member of the array. Your compiler might do you a better favor by rejecting the code altogether instead of merely emitting warnings.
Having entered a pointer to swap2() into the array anyway, over the compiler's warnings, how do you suppose the program could call that function correctly via the pointer? The type of the pointer requires function arguments to be ints; your compiler again performs the dubious service of accepting your code with only warnings instead of rejecting it.
Since the arguments in fact provided are the correct type, it might actually work on systems and under conditions where the representations of int and int * are compatible. That is no excuse, however, for writing such code.
Because pointers and ints are unchanged by the default argument promotions, one alternative would be to omit the prototype from your array declaration:
int (*swap[4])() = {swap1,swap2,swap3,swap4};
That says that each pointer points to a function that returns int and accepts a fixed but unspecified number of arguments of unspecified types. At the point of the call, the actual arguments will be subject to the default argument promotions, but that is not a problem in this case. This option does prevent the compiler from performing type checking on the arguments, but in fact you cannot do this correctly otherwise.
Your compiler might still warn about this, or could be induced to warn about it with the right options, but the resulting code nevertheless conforms and does the right thing, in the sense that it calls the pointed-to functions with the correct arguments.
To deal with the warnings first: You declare an array of functions which take int parameters. This means that swap2 is incompatible with the type of element for the array you put it in. This will generate a diagnostic.
Furthermore, when you call one of the functions in the array, the same array declaration tells the compiler that the parameters need to be ints not pointers to int. You get two diagnostics here, one for each parameter.
To fix the above all your functions need to have compatible prototypes with the element type of the array. Should it be int or int*? This brings us to the other problem.
C function arguments are always pass by value. This means that the argument is copied from the variable onto the stack (or into the argument register depending on the calling convention and argument count - for the rest of this post, I'll assume arguments are placed on the stack for simplicity's sake). If it's a literal, the literal value is put on the stack. If the values on the stack are changed by the callee no attempt is made by the caller, after the function returns, to put the new values back in the variables. The arguments are simply thrown away.
Therefore, in C, if you want to do the equivalent of call by reference, you need to pass pointers to the variables you use as arguments as per swap2. All your functions and the array should therefore use int*. Obviously, that makes one of swap1 and swap2 redundant.
The correct array definition is
int (*swap[4])(int*, int*) = {swap1, swap2, swap3, swap4};
and the definition of each function should be modified to take int* parameters. I'd resist the temptation to use int (*swap[4])() simply because it circumvents type safety. You could easily forget the & in front of an int argument when the called function is expecting a pointer which could be disastrous - the best case scenario when you do that is a seg fault.
The others have done great work explaining what the problems are. You should definitely read them first.
I wanted to actually show you a working solution for that sort of problem.
Consider the following (working) simple program :
// main.c
#include <stdio.h>
void swap1(int* aPtr, int* bPtr) {
printf("swap1 has been called.\n");
int tmp = *aPtr;
*aPtr = *bPtr;
*bPtr = tmp;
}
void swap2(int* aPtr, int* bPtr) {
printf("swap2 has been called.\n");
*aPtr += *bPtr;
*bPtr = *aPtr - *bPtr;
*aPtr -= *bPtr;
}
int main() {
int a = 1, b = 2;
printf("a is now %d, and b is %d\n\n", a, b);
// Declare and set the function table
void (*swapTbl[2])(int*, int*) = {&swap1, &swap2};
// Ask for a choice
int choice;
printf("Which swap algorithm to use? (specify '1' or '2')\n>>> ");
scanf("%d", &choice);
printf("\n");
// Swap a and b using the right function
swapTbl[choice - 1](&a, &b);
// Print the values of a and b
printf("a is now %d, and b is %d\n\n", a, b);
return 0;
}
First of, if we try to compile and execute it:
$ gcc main.c && ./a.out
a is now 1, and b is 2
Which swap algorithm to use? (specify '1' or '2')
>>> 2
swap2 has been called.
a is now 2, and b is 1
As myself and others mentioned in answers and in the comments, your functions should all have the same prototype. That means, they must take the same arguments and return the same type. I assumed you actually wanted to make a and b change, so I opted for int*, int* arguments. See #JeremyP 's answer for an explanation of why.

What is wrong with the following Code in C language?

I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting. So according to me answer should be option A. But in official GATE-2017 exam answer key, answer is given D. So am i wrong ? how ?
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int *assignval(int *x, int val){
*x = val;
return x;
}
void main(){
clrscr();
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
x = (int *)malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,10);
}
printf("%d\n",*x);
free(x);
getch();
}
(A) compiler error as the return of malloc is not typecast
appropriately.
(B) compiler error because the comparison should be made as x==NULL
and not as shown.
(C) compiles successfully but execution may result in dangling
pointer.
(D) compiles successfully but execution may result in memory leak.
In my opinion option D is only correct when int *x = (int *)malloc(sizeof(int)); is used.
There's no right answer among the choices offered.
The immediately obvious problems with the code, under assumption that the code is supposed to be written in standard C:
Standard library does not have <conio.h> header or <iostream.h> header.
void main() is illegal. Should be int main(). Even better int main(void)
clrscr(), getch() - standard library knows no such functions.
The second malloc leaks memory allocated by the first one (assuming the first one succeeds).
Result of second malloc is explicitly cast - bad and unnecessary practice.
The statement :
int *x = malloc(sizeof(int));
will not lead to compile error, as it declares x as a pointer to int and initializes it right afterwards. It did not have type void beforehand.
The statement :
x = (int *)malloc(sizeof(int));
causes a possible memory leak, as it reallocates the memory which is already allocated for x.
NOTE : However none of this answers is completely correct. This code will not compile for various reasons.
If this is your code, change :
void main()
to :
int main(void)
and also see why you should not cast the result of malloc.
Apart from that, clrscr(), getch(), <conio.h> and <iostream.h> are not recognized by standard library.
I observed that in line int *x = malloc(sizeof(int)); this code is trying to convert a void* into a int* without using proper typecasting.
There's more than a little debate about whether or not to cast malloc, but it's a stylistic thing. void * is safely promoted to any other pointer.
ISO C 6.3.2.3 says...
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Whatever you choose, pick one and stick with it.
The memory leak is here:
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
// Memory leak
x = (int *)malloc(sizeof(int));
The first malloc points x at allocated memory. The second malloc can only happen if the first succeeded (if x is true). The pointer to the memory allocated by the first malloc is lost.
Using a new variable would fix the leak, keeping in mind that the code is nonsense.
int *x = malloc(sizeof(int));
if(NULL==x) return;
x = assignval(x,0);
if(x){
int *y = malloc(sizeof(int));
if(NULL==y) return;
y = assignval(y,10);
free(y);
}
As a side note, void main() is technically not a violation of the ISO C standard, it is "some other implementation-defined manner".
5.1.2.2.1 says:
The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):
int main(int argc, char argv[]) { / ... */ }
or equivalent;) or in some other implementation-defined manner.
I'm guessing you're using a Windows compiler, that would be the "some other implementation". clang considers it an error.
test.c:8:1: error: 'main' must return 'int'
void main(){
^~~~
int
1 error generated.
you should never forget that a void * pointer can be assigned to all type of pointers. in IDEs like visual studio, you get a compile error if you do not perform casting while assigning a void * to <>. for example:
float *ptr = malloc(sizeof(float));//compile error in visual studio.
but if you compile it with GCC without typecasting, you won't get a compile error.

Calling C function from Fortran with pointers

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

Does printf function affect the life of variable?

This is my simple C program.
#include <stdio.h>
float*multiply(int, float);
main(){
int i =3;
float f = 3.50, *p;
p = multiply(i, f);
printf("%u\n", p);
printf("%f\n", *p);
return 0;
}
float *multiply(int ii, float ff){
float product = ii * ff;
printf("%f\n", product);
printf("%u\n", &product);
return (&product);
}
This program gives the following output:-
But, when I comment out the two "printf" statement in multiply function, It gives the following output:-
I am really sure I'm not doing any silly mistake. I am just commenting out two lines.
Can anyone tell me why is this happening? Is this OS/System related problem?
How is printf function increasing the life of the variable?
You are returning the address of the local, stack-based variable product which will result in undefined behavior.
Also, to print the value of a pointer, you should use %p instead of %u. http://www.cplusplus.com/reference/cstdio/printf/
This is simply an undefined behavior. The lifetime of the variable stays the same - it is limited to the time the function is running. Once the function has exited, all bets are off. Calling printf changes the state of the stack, so the results that you see are different. However, in both cases the results are undefined, meaning that your program can print anything or even crash.
You can detect this undefined behavior by running your program in valgrind.
Note: a proper way to print a pointer is printf("%p\n", (void*)&product);
As mentioned in other answers, by returning the address of product, a local variable, your results are undefined. However, if you return the value of product instead, the result is well defined and your program will work as expected:
#include <stdio.h>
float multiply(int ii, float ff){
float product = ii * ff;
return product;
}
int main(void){
int i =3;
float f = 3.50, p;
p = multiply(i, f);
printf("%p\n", &p);
printf("%f\n", p);
return 0;
}
0x7fff521cfac0
10.500000
If you compile this with the flag -Wall you will see this warning:
test.c:19:4: warning: function returns address of local variable [-Wreturn-local-addr]
This is because you return the memory address of product, and set float p to point to that address, but since that function has finished the memory it used is popped from the stack and no longer guaranteed to be there, meaning p can be pointing to garbage.
After printf() and scanf() sometimes you need to do fflush(stdin) or flushall(). Try that one.
The address of a local variable in a function depends on the state of the stack (the value of the SP register) at the point in execution when the function is called.
In other words, this address is not necessarily the same every time the function is called.
Therefore, returning the address of a local variable leads to undefined behavior.
You can observe the output of the following program as an example:
int func1()
{
int var = 1;
printf("%p\n",&var);
return var;
}
int func2()
{
int var = 2;
func1();
return var;
}
int main()
{
func1(); // main --> func1
func2(); // main --> func2 --> func1
return 0;
}
As implied by #chux in one of the comments below, the C-language standard does not dictate how variables should be allocated in memory. So the problem described above is the result of how most compilers allocate local variables in memory.

Resources