I have a C code in long file that is compiled using cc. But when I tried to compile on gcc it gives error. I took that particular code in small program and try to compile on cc but it failed over there.
Here is source:
#include <stdio.h>
int main (int argc, char **argv)
{
char unsigned FileName[100];
char test[100];
FileName[strstr(FileName,test) - FileName] = 0;
return 0;
}
This line is causing the problem:
FileName[strstr(FileName,test) - FileName] = 0;
error on CC is :
"foo.c", line 10: operands have incompatible types:
int "-" pointer to unsigned char
and on gcc is :
foo.c:10: error: invalid operands to binary - Both are same.
But when I compile original file on CC it compiled and just give a warning. Like this:
"dbtprc.c", line 643: warning: argument #1 is incompatible with prototype:
prototype: pointer to const char : "/usr/include/iso/string_iso.h", line 133
argument : pointer to unsigned char
"dbtprc.c", line 643: warning: improper pointer subtraction
Can you please help why here it is giving warning "improper pointer subtraction" and sample program it is showing error?
Don't you missed to include <string.h> ??
If yes, the prototype of strsrt is guessed and by default it returns an int, hence the invalid pointer operation.
Otherwise, it appears that the signedness mismatch is the cause of the warning/error.
Use a (char*)cast before the two occurence of your table and it will go.
Is there anything called Array Arithmetic in C? Read this:
Arrays are not Pointers.
And see how to use strstr().
void * bar;
void * foo;
...
foo = bar + 1;
That's undefined behaviour, right there! You are referring to a memory location that wasn't even allocated.
EDIT:
Now you have another problem: even though you sucessfully declared both arrays, you failed to clean/initialize them. Only god knows what strstr() will return to you.
The problem you have compiling this code is that strstr() takes 2 const char* and you defined Filename as unsigned: char unsigned FileName[100];
char *strstr(const char *haystack, const char *needle);
An error or a warning is not much different, just showing how serious the compiler believes the issue is.
But why do you use unsigned char for the filename? That's in conflict with strstr which only handles char*, both for its parameter and return type.
That's what the compilers try to tell you, in different ways.
Related
The following code snippet (correctly) gives a warning in C and an error in C++ (using gcc & g++ respectively, tested with versions 3.4.5 and 4.2.1; MSVC does not seem to care):
char **a;
const char** b = a;
I can understand and accept this.
The C++ solution to this problem is to change b to be a const char * const *, which disallows reassignment of the pointers and prevents you from circumventing const-correctness (C++ FAQ).
char **a;
const char* const* b = a;
However, in pure C, the corrected version (using const char * const *) still gives a warning, and I don't understand why.
Is there a way to get around this without using a cast?
To clarify:
Why does this generate a warning in C? It should be entirely const-safe, and the C++ compiler seems to recognize it as such.
What is the correct way to go about accepting this char** as a parameter while saying (and having the compiler enforce) that I will not be modifying the characters it points to?
For example, if I wanted to write a function:
void f(const char* const* in) {
// Only reads the data from in, does not write to it
}
And I wanted to invoke it on a char**, what would be the correct type for the parameter?
I had this same problem a few years ago and it irked me to no end.
The rules in C are more simply stated (i.e. they don't list exceptions like converting char** to const char*const*). Consequenlty, it's just not allowed. With the C++ standard, they included more rules to allow cases like this.
In the end, it's just a problem in the C standard. I hope the next standard (or technical report) will address this.
To be considered compatible, the source pointer should be const in the immediately anterior indirection level. So, this will give you the warning in GCC:
char **a;
const char* const* b = a;
But this won't:
const char **a;
const char* const* b = a;
Alternatively, you can cast it:
char **a;
const char* const* b = (const char **)a;
You would need the same cast to invoke the function f() as you mentioned. As far as I know, there's no way to make an implicit conversion in this case (except in C++).
However, in pure C, this still gives a warning, and I don't understand why
You've already identified the problem -- this code is not const-correct. "Const correct" means that, except for const_cast and C-style casts removing const, you can never modify a const object through those const pointers or references.
The value of const-correctness -- const is there, in large part, to detect programmer errors. If you declare something as const, you're stating that you don't think it should be modified -- or at least, those with access to the const version only should not be able to modifying it. Consider:
void foo(const int*);
As declared, foo doesn't have permission to modify the integer pointed to by its argument.
If you're not sure why the code you posted isn't const-correct, consider the following code, only slightly different from HappyDude's code:
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
Non-const types can only convert to const types in particular ways to prevent any circumvention of const on a data-type without an explicit cast.
Objects initially declared const are particularly special -- the compiler can assume they never change. However, if b can be assigned the value of a without a cast, then you could inadvertently attempt to modify a const variable. This would not only break the check you asked the compiler to make, to disallow you from changing that variables value -- it would also allow you break the compiler optimizations!
On some compilers, this will print 42, on some 43, and others, the program will crash.
Edit-add:
HappyDude: Your comment is spot on. Either the C langauge, or the C compiler you're using, treats const char * const * fundamentally differently than the C++ language treats it. Perhaps consider silencing the compiler warning for this source line only.
This is annoying, but if you're willing to add another level of redirection, you can often do the following to push down into the pointer-to-pointer:
char c = 'c';
char *p = &c;
char **a = &p;
const char *bi = *a;
const char * const * b = &bi;
It has a slightly different meaning, but it's usually workable, and it doesn't use a cast.
I'm not able to get an error when implicitly casting char** to const char * const *, at least on MSVC 14 (VS2k5) and g++ 3.3.3. GCC 3.3.3 issues a warning, which I'm not exactly sure if it is correct in doing.
test.c:
#include <stdlib.h>
#include <stdio.h>
void foo(const char * const * bar)
{
printf("bar %s null\n", bar ? "is not" : "is");
}
int main(int argc, char **argv)
{
char **x = NULL;
const char* const*y = x;
foo(x);
foo(y);
return 0;
}
Output with compile as C code: cl /TC /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with compile as C++ code: cl /TP /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with gcc: gcc -Wall test.c
test2.c: In function `main':
test2.c:11: warning: initialization from incompatible pointer type
test2.c:12: warning: passing arg 1 of `foo' from incompatible pointer type
Output with g++: g++ -Wall test.C
no output
I'm pretty sure that the const keyword does not imply the data can't be changed/is constant, only that the data will be treated as read-only. Consider this:
const volatile int *const serial_port = SERIAL_PORT;
which is valid code. How can volatile and const co-exist? Simple. volatile tells the compiler to always read the memory when using the data and const tells the compiler to create an error when an attempt is made to write to the memory using the serial_port pointer.
Does const help the compiler's optimiser? No. Not at all. Because constness can be added to and removed from data through casting, the compiler cannot figure out if const data really is constant (since the cast could be done in a different translation unit). In C++ you also have the mutable keyword to complicate matters further.
char *const p = (char *) 0xb000;
//error: p = (char *) 0xc000;
char **q = (char **)&p;
*q = (char *)0xc000; // p is now 0xc000
What happens when an attempt is made to write to memory that really is read only (ROM, for example) probably isn't defined in the standard at all.
I have something along the lines of:
#include <stdio.h>
typedef struct {
char s[100];
} literal;
literal foo()
{
return (literal) {"foo"};
}
int main(int argc, char **argv) {
printf("%s", foo().s);
return 0;
}
And I get this error when compiling it (with gcc):
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2
has type ‘char[100]’ [-Wformat=]
any1 has any ideas on how I can fix it? And what is wrong with that function return type?
EDIT
The problem (if not clear in the discussion) was the c standard gcc was using to compile the file. if you use -std=c99 or -std=c11 it works.
It is not an error but a warning, not all warnings that -Wall produces are sensible.
Here the compiler is "kind-of" right: before evaluation your argument is an array and not a pointer, and taking the address of a temporary object is a bit dangerous. I managed to get rid of the warning by using the pointer explicitly
printf("%s\n", &foo().s[0]);
Also you should notice that you are using a rare animal, namely an object of temporary lifetime, the return value or your function. Only since C99, there is a special rule that allows to take the address of such a beast, but this is a corner case of the C language, and you would probably be better off by using some simpler construct. The lifetime of the pointer ends with the end of the expression. So if you would try to assign the pointer to a variable, say, and use it later on in another expression, you would have undefined behavior.
Edit(s): As remarked by mafso in a comment, with C versions from before C99, it was not allowed to take the address of the return value of the function. As Pascal Cuoq notes, the behavior of your code is undefined even for C99, because between the evaluation of the arguments and the actual call of the function there is a sequence point. C11 rectified this by indroducing the object of temporary lifetime that I mentioned above.
I don't exactly why maybe someone with more knowledge in C than me can explain it but writing main() on this way:
int main(int argc, char **argv) {
literal b = foo();
printf("%s", b.s);
return 0;
}
The code prints "foo" correctly on GCC 4.5.4
I've started learning C and pointers and I've been working on tutorials on the internet. I assume that the code should work as it is in a tutorial, and it seems right to me, but I get a segmentation error. The code is:
#include <stdio.h>
#include <stdlib.h>
/*
*
*/
int main(int argc, char** argv) {
float fl = 3.14;
unsigned int addr = (unsigned int) &fl;
printf("fl's address=%u\n", addr);
printf("addr's contents = %.2f\n", * (float*) addr);
return (EXIT_SUCCESS);
}
The error that I get is
/Applications/NetBeans/NetBeans
6.9.1.app/Contents/Resources/NetBeans/ide/bin/nativeexecution/dorun.sh: line 33: 1626
Segmentation fault sh "${SHFILE}"
Does this have to do with me using a Mac or is there something wrong with the code?
Thanks a lot,
Niek
Try this instead:
int main(int argc, char** argv) {
float fl = 3.14;
float *addr = &fl;
printf("fl's address=%p\n", addr);
printf("addr's contents = %.2f\n", *addr);
return (EXIT_SUCCESS);
}
That may be undefined behaviour. There's no guarantee that an int and a pointer can hold the same value, and you should not be casting between them. Use a float* instead.
C99 6.3.2.3/5 and /6 state:
5: An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
6: Any pointer type may be converted to an integer type. Except as previously specified, the
result is implementation-defined. If the result cannot be represented in the integer type,
the behavior is undefined. The result need not be in the range of values of any integer
type.
Yes, the address space of pointer is not guaranteed to be the same as an int. In fact, this code gives me the following compilation warnings using gcc on a Mac Pro:
test.c:9: warning: cast from pointer to integer of different size
test.c:11: warning: cast to pointer from integer of different size
and a seg fault as well. I would consider samplebias' code.
The code seems to be correct, compiling with MinGW GCC and running gives the following output:
fl's address=2293528
addr's contents = 3.14
yes under win7 + mingw32, the code compiles\executes corrrectly
fl's address=2293572
addr's contents = 3.14
i think it's problem with MacOS only
The problem is the size of int. As #paxdiablo already said, there is no guarantee that an int is big enough to hold the same value as a pointer. Try long longinstead, but be warned, the code stays in the undefined behavior corner.
I am wondering why I can't compile an example from book. I simplify the example here to avoid posting example from a copyrighted book.
#include <stdio.h>
BYTE *data = "data";
int main()
{
printf("%s", data);
return 0;
}
When compile with g++, i get error,
error: invalid conversion from 'const char*' to 'BYTE*'
The program works by simply replacing BYTE with char, but I must be doing something wrong since the example comes from a book.
Please help pointing out the problem. Thanks.
BYTE isn't a part of the C language or C standard library so it is totally system dependent on whether it is defined after including just the standard stdio.h header file.
On many systems that do define a BYTE macro, it is often an unsigned char. Converting from a const char* to an unsigned char* would require an explicit cast.
The following code snippet (correctly) gives a warning in C and an error in C++ (using gcc & g++ respectively, tested with versions 3.4.5 and 4.2.1; MSVC does not seem to care):
char **a;
const char** b = a;
I can understand and accept this.
The C++ solution to this problem is to change b to be a const char * const *, which disallows reassignment of the pointers and prevents you from circumventing const-correctness (C++ FAQ).
char **a;
const char* const* b = a;
However, in pure C, the corrected version (using const char * const *) still gives a warning, and I don't understand why.
Is there a way to get around this without using a cast?
To clarify:
Why does this generate a warning in C? It should be entirely const-safe, and the C++ compiler seems to recognize it as such.
What is the correct way to go about accepting this char** as a parameter while saying (and having the compiler enforce) that I will not be modifying the characters it points to?
For example, if I wanted to write a function:
void f(const char* const* in) {
// Only reads the data from in, does not write to it
}
And I wanted to invoke it on a char**, what would be the correct type for the parameter?
I had this same problem a few years ago and it irked me to no end.
The rules in C are more simply stated (i.e. they don't list exceptions like converting char** to const char*const*). Consequenlty, it's just not allowed. With the C++ standard, they included more rules to allow cases like this.
In the end, it's just a problem in the C standard. I hope the next standard (or technical report) will address this.
To be considered compatible, the source pointer should be const in the immediately anterior indirection level. So, this will give you the warning in GCC:
char **a;
const char* const* b = a;
But this won't:
const char **a;
const char* const* b = a;
Alternatively, you can cast it:
char **a;
const char* const* b = (const char **)a;
You would need the same cast to invoke the function f() as you mentioned. As far as I know, there's no way to make an implicit conversion in this case (except in C++).
However, in pure C, this still gives a warning, and I don't understand why
You've already identified the problem -- this code is not const-correct. "Const correct" means that, except for const_cast and C-style casts removing const, you can never modify a const object through those const pointers or references.
The value of const-correctness -- const is there, in large part, to detect programmer errors. If you declare something as const, you're stating that you don't think it should be modified -- or at least, those with access to the const version only should not be able to modifying it. Consider:
void foo(const int*);
As declared, foo doesn't have permission to modify the integer pointed to by its argument.
If you're not sure why the code you posted isn't const-correct, consider the following code, only slightly different from HappyDude's code:
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
Non-const types can only convert to const types in particular ways to prevent any circumvention of const on a data-type without an explicit cast.
Objects initially declared const are particularly special -- the compiler can assume they never change. However, if b can be assigned the value of a without a cast, then you could inadvertently attempt to modify a const variable. This would not only break the check you asked the compiler to make, to disallow you from changing that variables value -- it would also allow you break the compiler optimizations!
On some compilers, this will print 42, on some 43, and others, the program will crash.
Edit-add:
HappyDude: Your comment is spot on. Either the C langauge, or the C compiler you're using, treats const char * const * fundamentally differently than the C++ language treats it. Perhaps consider silencing the compiler warning for this source line only.
This is annoying, but if you're willing to add another level of redirection, you can often do the following to push down into the pointer-to-pointer:
char c = 'c';
char *p = &c;
char **a = &p;
const char *bi = *a;
const char * const * b = &bi;
It has a slightly different meaning, but it's usually workable, and it doesn't use a cast.
I'm not able to get an error when implicitly casting char** to const char * const *, at least on MSVC 14 (VS2k5) and g++ 3.3.3. GCC 3.3.3 issues a warning, which I'm not exactly sure if it is correct in doing.
test.c:
#include <stdlib.h>
#include <stdio.h>
void foo(const char * const * bar)
{
printf("bar %s null\n", bar ? "is not" : "is");
}
int main(int argc, char **argv)
{
char **x = NULL;
const char* const*y = x;
foo(x);
foo(y);
return 0;
}
Output with compile as C code: cl /TC /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with compile as C++ code: cl /TP /W4 /Wp64 test.c
test.c(8) : warning C4100: 'argv' : unreferenced formal parameter
test.c(8) : warning C4100: 'argc' : unreferenced formal parameter
Output with gcc: gcc -Wall test.c
test2.c: In function `main':
test2.c:11: warning: initialization from incompatible pointer type
test2.c:12: warning: passing arg 1 of `foo' from incompatible pointer type
Output with g++: g++ -Wall test.C
no output
I'm pretty sure that the const keyword does not imply the data can't be changed/is constant, only that the data will be treated as read-only. Consider this:
const volatile int *const serial_port = SERIAL_PORT;
which is valid code. How can volatile and const co-exist? Simple. volatile tells the compiler to always read the memory when using the data and const tells the compiler to create an error when an attempt is made to write to the memory using the serial_port pointer.
Does const help the compiler's optimiser? No. Not at all. Because constness can be added to and removed from data through casting, the compiler cannot figure out if const data really is constant (since the cast could be done in a different translation unit). In C++ you also have the mutable keyword to complicate matters further.
char *const p = (char *) 0xb000;
//error: p = (char *) 0xc000;
char **q = (char **)&p;
*q = (char *)0xc000; // p is now 0xc000
What happens when an attempt is made to write to memory that really is read only (ROM, for example) probably isn't defined in the standard at all.