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.
Related
#include <stdio.h>
#include <stdlib.h>
void main (){
char* shell = getenv("MYSHELL");
if (shell)
printf("%x\n", (unsigned int)shell);
}
shell.c: In function ‘main’:
shell.c:7:19: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
7 | printf("%x\n", (unsigned int)shell);
First of all, that's a warning, not an error. The compiler will still allow you to compile your program when it has warnings (though many programmers would advise fixing those warnings), but if you get a compiler error your code will not compile at all.
The reason for the warning is that char* is a pointer type, which on x64 architectures is essentially a 64-bit integer. int, and by extension unsigned int, is a 32-bit integer. If you want to silence the error, you could cast to unsigned long instead (and change the %x to %lx), but there's a much easier way. There is a format specifier for pointers, %p, which you can simply use with any pointer.
So if you want to silence the warning I'd recommend changing your print statement to printf("%p\n", shell);
I am very new to pointers in C and I am having trouble making sense of this error or a pointer not accessing the memory to store an actual value.
#include <stdio.h>
int main() {
int a;
int *pA = &a;
a = 9;
*pA = 4;
int *pA2 = &a;
printf("pA = %p, *pA = %d, *pA2 = %d\n", *pA, *pA2);
}
In (virtual) reality, shouldn't `pA2 spit out 4 as well? Instead it is giving what looks like a number associated with memory address.
Thanks,
You have left off an argument to printf(). Consider the following:
#include <stdio.h>
int main() {
int a;
int* pA= &a;
a = 9;
*pA = 4;
int* pA2 = &a;
printf("pA=%p, *pA=%d, *pA2=%d\n", (void*) pA, *pA, *pA2);
}
It outputs a memory address, 4, and 4 again. Try it online.
For each % to be substituted, you must pass an extra argument to printf().
When you leave out an argument, the function will try to grab an argument anyway – this leads to undefined behaviour. In your case it managed to take a number (presumably from the stack). It could also crash the program – since the behaviour is undefined, there is no way to consistently predict it.
Also note that I have cast your pointer to a void* for the output – the %p format specifier requires it. Other pointers will work most of the time, but are not guaranteed to. Read more about printf() here.
To help you detect similar and other problems in the future, turn on compiler warnings. In the beginning, these may seem overwhelming, but they are really helpful. See your code compiled with the compiler flags suggested by #Davislor's comment here.
I have added -Werror to these. It forces you to actually deal with the warnings since the compiler won't generate an executable as long as your code generates warnings.
I have also added the same flags to the first link in my answer so you can see it does not generate any warnings.
I am trying to create a C program in a Linux VM that uses a char array. I found that every time I try to do anything to the array, e.g. sizeof(), I get a segmentation fault. I wrote a test program that just made an array and got sizeof() as a test, and sure enough I get the same error.
I think this is related to the program running in a VM. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define ARR_LENGTH(x) sizeof(x) / sizeof(x[0])
int main()
{
printf("Hllo world!\n");
int sent = 10;
char hello[] = {'a','b','c','d','e','f','g','h'};
printf(sizeof(hello));
printf(ARR_LENGTH(hello));
return 0;
}
Am I missing something, or is the VM likely the problem?
You just need to read the printf() documentation carefully. It doesn't take an integer as its first argument.
The problematic lines are:
printf(sizeof(hello));
printf(ARR_LENGTH(hello));
It should be:
printf("%zu\n", sizeof(hello));
printf("%zu\n", ARR_LENGTH(hello));
(%zu is the format specifier to print size_t values).
My gcc compiler produces the warning:
warning: passing argument 1 of ‘printf’ makes pointer from integer
without a cast [-Wint-conversion]
for those two statements. Up the compiler warning levels (in case you don't get them alrready).
I have a serious problem with writing an App on Linux.
I have this code
#include <stdio.h>
int main()
{
char ar[10][10];
strcpy(ar[1], "asd");
strcpy(ar[2], "fgh");
int test[2];
test[1] = (int)ar[1];
printf("%s %x | %s %x\n\n", ar[1], ar[1], test[1], test[1]);
return 0;
}
And it works on Windows well, but when i want to run this on Linux i got
Segmentation Fault or Unauthorized Access to memory.
Your program invokes undefined behavior. It assumes that a pointer will fit into an int, which isn't required. Usually pointers will fit on Unix boxes and fail on Windows; but you should use an appropriate integer type, such as intptr_t from stdint.h if you need to do such conversions. Note that strictly speaking the integer must be cast back to a pointer type before being passed to printf.
Using a pointer type to printf and a large enough integral type results in correct behavior: http://ideone.com/HLExMb
#include <stdio.h>
#include <stdint.h>
int main(void)
{
char ar[10][10];
strcpy(ar[1], "asd");
strcpy(ar[2], "fgh");
intptr_t test[2];
test[1] = (intptr_t)ar[1];
printf("%s %x | %s %x\n\n", ar[1], ar[1], (char*)test[1], (char*)test[1]);
return 0;
}
Note though that casting pointers into integral types is generally frowned upon and is likely to result in program bugs. Don't go there unless you absolutely need to do so for one reason or another. When you're starting out in C it is unlikely that you'll ever need to do this.
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.