Check out this code
#include<stdio.h>
int main()
{
const int a=7;
int *p=&a;
(*p)++;
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
getch();
}
The output you get for this is
*p=8
p=1245064
a=8
&a1245064
How is this possible?? We declared variable a as constant. Doesnt this mean that the location pointed to by a can never be changed during the course of pgm execution??
That's undefined behavior - in your case it is working as you described, but it could just as well crash the program or cause any other problems. In your case const doesn't prevent the compiler from allocating the variable in modifiable memory, so you technically can modify it by obtaining a pointer to that variable and working through the pointer.
Undefined behaviour is not to be relied upon ;-)
Would you really want to use C if it actually prevented that from working? The fact it works that way is very much in the spirit of the language.
Reading your comment "it only gives a warning saying suspicious pointer conversion" it should be clear enough to deduce that you are doing something illegal.
You are assigning to a int * variable a const int * value.
The fact that C hasn't any runtime checkings to prevent you from modifying that memory address doesn't imply that it's allowed! (and in fact, the static type system checking is telling you that).
If yours doesn't detect this automatically, just get yourself a decent compiler. E.g clang gives me 4 problems with your code:
clang -c -o test-const.o test-const.c
test-const.c:17:7: warning: initializing 'int const *' discards qualifiers, expected 'int *' [-pedantic]
int *p=&a;
^ ~~
test-const.c:19:20: warning: conversion specifies type 'unsigned int' but the argument has type 'int *' [-Wformat]
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
~^ ~
test-const.c:19:32: warning: conversion specifies type 'unsigned int' but the argument has type 'int const *' [-Wformat]
printf("*p=%d\np=%u\na=%d\n&a%u",*p,p,a,&a);
~^ ~~
test-const.c:20:2: warning: implicit declaration of function 'getch' is invalid in C99 [-Wimplicit-function-declaration]
getch();
^
4 diagnostics generated.
These are all serious problems.
Related
according to what i learned about function variables they should not 'live' outside their function scope,thus returning a local function variable should cause an error, i do get compiling warnings that i do expect, but it makes no sense to me because the program do work and i am little confused
i wrote the following program:
int * test(int x) {
int f=x+1;
return f; //- int to pointer conversion,idk why this works
}
int main () {
int x = 10;
printf("%d\n",test(x));
}
I first expected the program to crash because we make conversion from int type to pointer at function return, but apparently the program prints 11 which i did not expect, i know this is really bad to write like this anyways it was just a coincidence i wrote something like this and it worked and I had alot of questions after that
the warnings i expected to get :
Solution.c: In function ‘test’:
Solution.c:10:12: warning: return makes pointer from integer without a cast [-Wint-conversion]
return f;
^
Solution.c: In function ‘main’:
Solution.c:15:14: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("%d\n",test(x));
~^ ~~~~~~~
%ls
can anyone explain how this program works ?
You tell the compiler that function test() should return return a pointer to an integer. You don't. You return a value of an integer.
The compiler says, "You're probably doing unintentional stuff here, just sayin'. I'll cast this integer to a pointer for you."
Then the compiler says, "You want to print the value of an integer here but what you're giving is a pointer. Just sayin'. I'll cast this pointer to an integer for you."
#include<stdio.h>
#include<string.h>
void fun(char** a)
{
strcpy(*a, "ponky" );
}
int main()
{
char a[100] = "pinky";
fun(&a );
printf("\n %s \n", a );
return 0;
}
Copying a string in a function through double pointer.
Why the above program gives segmentation fault?
note: I suspect this question to be a duplicate and I've found many similar questions but I haven't found an exact duplicate. Therefore I post an answer. Should someone find an exact duplicate I'll remove this answer.
Why the above program gives segmentation fault?
The short answer is that you have a type mismatch when calling fun. You don't give fun a "pointer to pointer to char" as it expects. Consequently, it fails big time.
But what do you then pass to fun? And how should you have found out that something was wrong?
The answer is: Set compiler warning level high and consider all warnings to be errors
For gcc that could be:
gcc -xc -Wall -pedantic -Werror main.c
(Other compilers have similar options)
On my system I get:
In function 'main':
error: passing argument 1 of 'fun' from incompatible pointer type [-Werror=incompatible-pointer-types]
13 | fun(&a );
| ^~
| |
| char (*)[100]
note: expected 'char **' but argument is of type 'char (*)[100]'
3 | void fun(char** a)
| ~~~~~~~^
so it's clear that something is wrong and the following line tells it all:
note: expected 'char **' but argument is of type 'char (*)[100]'
you pass char (*)[100] instead of char **
But what is char (*)[100]?
It's a "pointer to an array of char". Since fun uses it as "pointer to pointer to char" you have undefined behavior (which in your case resulted in a seg fault). That is - fun would expect *a to be a "pointer to char" but you passed "pointer to an array of char" so *a is not a "pointer to char".
It's undefined behavior so we can't tell what is going on. However, on many systems it will read the string "pinky" and interpretate it as a pointer to char which will fail big time.
I tried to using two different functions from sting.h header file (without including it) strlen() and strtok(). Strlen executed successfully without any error (but some warnings), strtok failed at runtime. Why is it that strlen() function worknig gine but not strtok() if I don't include the header file? I suppose there is something in the linking process that I don't understand. Please clarify for such behavior. However, the program terminates successfully if I print a as '%c' instead of '%s' (strtok returns a garbage value).
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
}
WARNINGS:
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
OUTPUT:
$ ./a.out
Length of sting is 16
CODE:
int main()
{
char string[] = "This is a String";
printf("\nLength of sting is %d\n",strlen(string));
char *a = strtok(string," ");
printf("%s",a);
}
WARNINGS:
$ gcc hello.c
hello.c: In function ‘main’:
hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default]
hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]
hello.c:5:12: warning: initialization makes pointer from integer without a cast [enabled by default]
OUTPUT:
$ ./a.out
Length of sting is 16
Segmentation fault (core dumped)
The linking is done implicitly for most of the C standard library. You just have to include the headers of what you use (that's the warnings).
When you don't, your compiler (which is compiling your code as ANSI C) assumes the functions return int, instead of their documented return types. Your program has undefined behavior because of that. Always heed warnings!
You must include the headers string.h and stdio.h.
The first program works because you were lucky enough in that strlen is supposed to return an integer (a size_t to be exact, but it appears on your system the value representation for integers and size_t lets the program slide through).
The second fails because strtok returns a char* but it's assumed an int due to your missing include directives. int and char* are not compatible types, so the "pointer" you get isn't valid.
Sting is a singer, not a C header... Still, the problem is that in C, when you use functions that were not declared, the compiler guesses them to have the types of the arguments you first pass to them and returning an int.
That's the reason why you get all these warnings: several undeclared functions you use don't actually have the deduced signature (although they are not too wrong, and end up working), and the real strtok returns a pointer, not an int (the warning in facts says that you are assigning an int to a pointer without a cast). The crash you are getting most probably comes from the fact that the original pointer is 64 bit, but is truncated to 32 bit when is erroneously considered an int before being assigned to a.
Still, the point to take home is: include headers and don't ever rely on implicit function declaration. It's a dangerous mess that exists only for backward compatibility reasons.
I am using gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 and compiling following code:
void main()
{
float f= 10.0;
char *str = "hello";
printf("f=%.1f str=%s\n",str, f);
}
Compiler is showing Warning that is expected:
prac.c: In function 'main':
prac.c:8:1: warning: format '%f' expects argument of type 'double', but argument 2 has type 'char *' [-Wformat=]
printf("f=%.1f str=%s\n",str, f);
^
prac.c:8:1: warning: format '%s' expects argument of type 'char *', but argument 3 has type 'double' [-Wformat=]
However, while executing this program, output is auto-corrected.
# ./a.out
f=10.0 str=hello
How this is happening.
Which feature of compiler is doing this.
Any way to disable this auto-correction.
That's not "auto correction," it's "undefined behavior." It's happening because floating-point variables may be (or may not be!) passed to functions in a separate space vs. integral types. So when you pass one pointer (or int) and one double, they are still using the first slot for each type, even though you specified them in the wrong order.
Compile with -Wformat=2 and -Werror and you will never see this problem again, because GCC (and Clang) will refuse to build such code.
#include<stdio.h>
struct test{
int a;
int b;
}m;
int main()
{
m.a=5;m.b=7;
struct test *p;
p = &m;
printf("p[0] = %d\n",*(p+0));
printf("p[1] = %d\n",*(p+1));
return 0;
}
I get the following Ouput:
p[0] = 5
p[1] = 0
Can someone please explain this behavior? Is there a way to print all struct members using index?
Sorry about the typo.
(Updated)
As I could print 1st element using index 0 , though the type of pointer is of "struct test type" and 1st member is an integer , I could get the correct value. Hence, the question triggered about the cause of this behavior. And if all the members can be accessed using the index just like the 1st member was accessed.
In your code,
printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));
invokes undefined behavior as
you are passing wrong type of argument for %d format specifier.
You're accessing out of bound memory by saying *(p+1)
So, the output cannot be explained or justified in any way.
Now, that said, let's analyze the code a bit.
First of all,
p = &a;
is wrong, as there is no variable called a. There is a member variable a for the structure variable m, which can be accessed as m.a. So, you can somehow write
p = (struct test*) &m.a;
Now, using the address of the first element of the structure as the structure address is valid as there is no padding at the beginning of the structure. But that does not mean, you can apply pointer arithmetic directly on the structure pointer p and get each member variable, mainly because
There can be padding between two elements
The pointer p is of type struct test (Though you can get around by casting)
Get a proper compiler. Compiled with default settings on GCC 5, the compilation spits out:
foo.c: In function ‘main’:
foo.c:12:10: error: ‘a’ undeclared (first use in this function)
p = &a;
^
foo.c:12:10: note: each undeclared identifier is reported only once for each function it appears in
foo.c:13:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+0));
^
foo.c:14:12: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+1));
^
Perhaps you meant p = &m;.
After that your code invokes undefined behaviour. %d expects that the corresponding argument be an int, yet you provide a struct test. Furthermore on the latter print, the pointer is pointing to uninitialized memory after the m, and garbage is printed. Even the fact that you had 5 printed in the first case cannot be relied on. The C standard does not explain that why or why not this happens, the C standard says "at this time it is ok for the compiler to generate code that prints 42342, crash the program, or do whatever else, and it is fine by this standar d."
In C compilers the warnings usually mean "standard violations" in which case undefined behaviour is probable. A newcomer to C programming language should always consider all compiler warnings especially with default settings as being fatal errors.
I compiled your code with gcc and i got.
In function ‘main’:
error: ‘a’ undeclared (first use in this function)
p = &a;
^
note: each undeclared identifier is reported only once for each function it appears in
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+0));
^
warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct test’ [-Wformat=]
printf("p[0] = %d\n",*(p+1));
Assuming you meant p=&m, here is my explanation
printf("p[0] = %d\n",*(p+0));
printf("p[0] = %d\n",*(p+1));
First analyse whether deferring pointer like you did in printf function is correct or not.
The *(p+0) will give you the access to the struct test variabe m. As, you have assigned the address of a variable of type struct test to the pointer p, deferring pointer *p or *(p+0) will give you the access to the variable m. But the address assigned to the pointer is of a single variable not of the array of type struct test, deferring (p+1) will give you UNDEFINED BEHAVIOR. For example, *(p+1) would have worked if (not in printf statement)
struct test m[20];
struct test *p;
(*(p+0)).a=2;
(*(p+1)).a=5;
Is there a way to print all struct members using index?
You can. But there is no overloading of operators in c. So, you can achieve this by -
printf("a=%d, b=%d", p->a, p->b);
If pointer p points to array of type struct test, then you can use index in printf as
printf("a=%d, b=%d of %dth element", p[i].a, p[i].b, i);
My suggestion for your future code experimentation will be first analyse warning and error given by your code. The warnings can help to rectify most of the bugs in your code. I always compile my c/c++ code with gcc/g++ compiler and use flags like -Wall, -Wshadow, -Wextra. You can google a warning if you don't understand it.
You are assigning the address of a to p directly. a is a member of m and so cannot be accessed directly. And as of your code, you should use an integer pointer for your arithmetic.
you need to modify a part of your code
struct test *p;
p = &a;
to
int *p;
p = &m.a;
now the code should work as you desire.
First, you have a typo in your code.
Please correct it from p = &a; to p = &m;, so that the error complained by the compiler shall be removed.
Second, I guess you expect the output to be p[0] = 5 and p[1] = 7.
To achieve that, modify your code from
printf("p[0] = %d\n",*(p+0));
printf("p[1] = %d\n",*(p+1));
to
printf("p[0] = %d\n",p->a);
printf("p[1] = %d\n",p->b);
can work.