I wrote a little little program in C, and I expected an error with vectors.
#include <stdlib.h>
#include <stdio.h>
main(){
int vet[0];
vet[0] = 1;
vet[1] = 2;
vet[2] = 2;
vet[3] = 2;
vet[4] = 2;
vet[5] = 2;
vet[6] = 2;
vet[7] = 2;
int x;
for(x=0;x<19;x++) printf("%d\n", vet[x]);
system("pause");
}
Before writing this code I thought that to add an element to a vector, moreover his size, I should call the malloc function, but then I discovered that also without the malloc function the code works fine. So my question is, why should I use the malloc function if in this case it's useless? And why should I write the dimension of a vector when I initialize it ?
Because, by writing to memory you never allocated, you are causing undefined behaviour. Sometimes it works, sometimes it doesn't, sometimes it makes your dog explode.
That's cute, but let's change the program a little by adding another such "vector":
#include <stdio.h>
int main(void){
int vet[0];
int vex[0];
vet[0] = 1;
vet[1] = 2;
vet[2] = 2;
vet[3] = 2;
vex[0] = 3;
vex[1] = 3;
vex[2] = 3;
vex[3] = 3;
int x;
for(x=0;x<4;x++) printf("%d\n", vet[x]);
}
I guess you could expect the program to print 1 2 2 2. I actually get 1 3 2 3. What do you get?
Unexpected things like this happen when you use something that causes "undefined behavior."
You should define array like;
int vet [8];
Otherwise it will invoke undefined behavior (which is the case in your program) as memory is not allocated for vet.
And also the loop
for(x=0;x<19;x++)
is going out of bounds which also invokes undefined behavior. Therefore it should be
for(x=0;x<8;x++)
Also change main definition to int main() or int main(void).
Standard C doesn't even permit zero sized arrays, not even for variable length arrays. It's undefined behavior. And you try to access out of array boundary, another undefined behavior.
In another word, it may happen to work here and it may not be working in another machine.
Related
When I compile this code :
int main() {
int a = 10;
int *p = &a;
printf("%p",p) // or printf("%p",&a);
return 0;
}
it prints 0022ff38.
Then this code :
int a=10;
int *p =(int *)0x22ff38;
printf("%d",*p); //does not output 10;
should print 10, but it output another thing(2293560).
But when I edit the code, and add a single line :
int main() {
int a = 10;
int *p =(int *)0x22ff38;
printf("%p",&a);
printf("%d",*p); // Now it prints correctly:10
return 0;
}
Every thing is ok!.
Questions:
Why my code does not output a value in first code?
What is usage of this way addressing pointers? is it useful?
Edit :
I have no problem in Linux, because in Linux every time that I run the code, the variable address changes and program output segmentation fault. but in windows address remains the same, and it is expected that manual addressing work in windows.
Compilers are smarter than you think. For example, given this code:
int main() {
int a=10;
int *p =(int *)0x22ff38;
printf("%d",*p);
}
The compiler is going to see that a is never even used. So it will never bother to actually allocate any memory for it.
If you add a printf("%d", a), the compiler might only put a in a register and never in memory.
Fundamentally, you can't assume that two programs will put variables in the same place in memory.
I'm trying to do something with an array (malloc-ed), namely arr of a custom struct. The array is passed by reference to a function. I get a segfault whenever I tried to index anything other than arr[0] in the function at runtime (e.g (*arr[1])->i = 3;). Why is this happening?
The full source code is:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef struct{
int i;
float f;
}foo;
void doSomething(foo ***arr);
int main()
{
foo **arr = (foo**) malloc (SIZE * sizeof(foo*));
int i;
for(i = 0; i < SIZE; i++)
arr[i] = (foo*)malloc(sizeof(foo));
arr[1]->i = 1;
printf("Before %d\n",arr[1]->i );
doSomething(&arr);
printf("After %d\n",arr[1]->i );
return 0;
}
void doSomething(foo ***arr)
{
(*arr[1])->i = 3;
}
Your problem is the line
(*arr[1])->i = 3;
Because the subscripting operator's evaluation precedes the dereferencing's evaluation it is equivalent to the following:
(*(arr[1]))->i = 3;
This is obviously wrong. You need
(*arr)[1]->i = 3;
therefore.
Notes:
do not cast the result of malloc
add #include <stdlib.h> to resolve the warning
adding an extra level of indirection (foo*** pointing to foo**) is unnecessary; just copy by value
(in addition to the upper note) a good old 1D array should actually be sufficient in your case
call free after malloc
The warning you get is because you forgot to #include <stdlib.h>, so malloc is not declared, so the compiler assumes it should return int. This can lead to all kinds of fun problems. (And you should remove those casts.)
The other problem is in this line: (*arr[1])->i = 3;
Postfix operators (like []) bind tighter than prefix operators (like *), so *arr[1] parses as *(arr[1]).
You can write (*arr)[1]->i instead to fix this, but as it turns out, your function never actually modifies *arr, so there's no reason to pass arr (the other arr, the one in main)'s address to it. Just do this:
void doSomething(foo **arr)
{
arr[1]->i = 3;
}
and call it as doSomething(arr).
I'm basically curious if you could do something like this, without the use of pointers:
int myVariable = 0;
int varPointer = &myVariable;
*varPointer += 1; //This obviously won't work, but explains the concept
Yes, I know you can do this with pointers. I want to know if it can be done without pointers.
EDIT>
I want to be able to refer to an address contained in a variable without pointers.
The question is basically, "Can you achieve pointer functionality without using actual pointers? If so, how?"
This code uses integer arithmetic instead of pointer arithmetic:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
int myVariable = 0;
uintptr_t varPointer = (uintptr_t)&myVariable;
varPointer += sizeof myVariable;
return 0;
}
You say in comments:
pointers /can/ contain addresses, but do not necessarily.
Pointer variables must either be null pointers or contain the address of an object. If your code appears to do otherwise then your program has already caused undefined behaviour.
"Hex" has nothing to do with it; base 16 is a way of outputting numbers and you can use any base you like.
Bear in mind that pointers do not necessarily correspond to numbers. On platforms where they don't, then uintptr_t will not exist.
#include <stdio.h>
#include <stdint.h>
int main(void){
int myVariable = 0;
intptr_t varPointer = (intptr_t)&myVariable;
*(int*)varPointer += 1;
printf("%d\n", myVariable);
return 0;
}
I have a piece of code where I am trying to return the square of the value pointed to by *ptr.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
main()
{
int a=8,t;
t=square(&a);
printf("%d",t);
}
Its working fine for me but author of this code said it might not work because of following reason:
Because it's possible for the value of *ptr to change unexpectedly, it is possible for a and b to be different. Consequently, this code could return a number that is not a square!. The correct way to do is
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
I really wanted to know why he said like that?
The idea of the volatile keyword is exactly to indicate to the compiler that a variable marked as such can change in unexpected ways during the program execution.
However, that does not make it a source of "random numbers" - it just advises the compiler - what is responsible for actually changing the variable contents should be another process, thread, some hardware interrupt - anything that would write to the process memory but not inlined in the function where the volatile declaration finds itself. In "older times" (compilers with less magic) everything it did was preventing the compiler from caching the variable value in one of the CPU registers. I have no idea on the optimisations/de-optimistions strategies triggered by it by modern compilers - but it will at least do that.
In the absense of any such external factor, a "volatile" variable is just like any other. Actually - it is just like any other variable - as variables not marked as volatile can also be changed by the same external causes (but the compiled C code would not be prepared for that in this case, which might lead to incorrect values being used).
Since the question has an accepted and correct answer, I will be brief: here is a short program that you can run to see the incorrect behavior happening for yourself.
#include <pthread.h>
#include <math.h>
#include <stdio.h>
int square(volatile int *p) {
int a = *p;
int b = *p;
return a*b;
}
volatile int done;
void* call_square(void* ptr) {
int *p = (int*)ptr;
int i = 0;
while (++i != 2000000000) {
int res = square(p);
int root = sqrt(res);
if (root*root != res) {
printf("square() returned %d after %d successful calls\n", res, i);
break;
}
}
done = 1;
}
int main() {
pthread_t thread;
int num = 0, i = 0;
done = 0;
int ret = pthread_create(&thread, NULL, call_square, (void*)&num);
while (!done) {
num = i++;
i %= 100;
}
return 0;
}
The main() function spawns a thread, and modifies the data being squared in a loop concurrently with another loop calling the square with a volatile pointer. Relatively speaking, it does not fail often, but it does so very reliably in less than a second:
square() returned 1353 after 5705 successful calls <<== 1353 = 33*41
square() returned 340 after 314 successful calls <<== 340 = 17*20
square() returned 1023 after 5566 successful calls <<== 1023 = 31*33
First understand what's volatile: Why is volatile needed in C?
and then, try to find answer by yourself.
It's a game of volatile and hardware world. :-)
Read answer given by Chris Jester-Young:
volatile tells the compiler that your variable may be changed by other means, than the code that is accessing it. e.g., it may be a I/O-mapped memory location. If this is not specified in such cases, some variable accesses can be optimised, e.g., its contents can be held in a register, and the memory location not read back in again.
If there is more than one thread, the value the pointer points to might change inbetween statement "a = *ptr" and statement "b = *ptr". Also: you want the square of a value, why put it into two variables?
In the code you present then there is no way for the variable a that is defined in your main to be modified whilst square is running.
However, consider a multi-threaded program. Suppose that another thread modified the value to your your pointer refers. And suppose that this modification took place after you had assigned a, but before you had assigned b, in the function sqaure.
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//the other thread writes to *ptr now
b = *ptr;
return a * b;
}
In this scenario, a and b would have different values.
The author is correct (if *ptr will be changed by other threads)
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
//between this two assignments *ptr can change. So it is dangerous to do so. His way is safer
b = *ptr;
return a * b;
}
Because the value of the pointer *ptr might change between the first affection and the second one.
I don't think the value of *ptr can change in this code barring an extremely unusual (and non-standards-compliant) runtime environment.
We're looking at the entirety of main() here and it's not starting up other threads. The variable a, whose address we are taking, is a local in main(), and main() doesn't inform any other function of that variable's address.
If you added the line mysterious_external_function(&a); before the t=square(&a) line, then yes, mysterious_external_function could start a thread and diddle the a variable asynchronously. But there's no such line, so as written square() always returns a square.
(Was the OP a troll post, by the way?)
I see some answers with *ptr can be changed by other threads. But this cannot happen since *ptr is not a static data variable. Its a parameter variable and local and parameter variables being hold inside stack. Each thread has its own stack section and if *ptr has been changed by another thread, it should not effect the current thread's.
One reason why the result might not give the square can be an HW interrupt might happen before assigning b = *ptr; operation as indicated below:
int square(volatile int *ptr) {
int a,b;
a = *ptr; //assuming a is being kept inside CPU registers.
//an HW interrupt might occur here and change the value inside the register which keeps the value of integer "a"
b = *ptr;
return a * b;
}
Example code:
#include <stdio.h>
int main (){
int *p;
{
int v = 1;
p = &v;
}
printf("%d\n", *p);
return 0;
}
This code works fine, but I'm not sure if there's a guarantee that the address of v will be preserved.
There is no guarantee.
Once v goes out of scope, doing anything with it at all (even via a pointer) is considered Undefined Behavior.
As with any other undefined behavior, just because it works on one operating system, compiler, compiler version, time of day, etc, doesn't mean it will work for another.
To add on Merlyn's answer, one case where this would probably result in behavior you didn't intend is the following:
#include <stdio.h>
int main (){
int *p;
{
int v = 1;
p = &v;
}
{
int w = 2;
printf("%d\n", w);
}
printf("%d\n", *p);
return 0;
}
The compiler may optimize this by having v and w share the same allocation on the stack. Again, the compiler might also not optimize this -- that's why the behavior of using pointers to variables after their enclosing block ends isn't defined. The program might output "2" and "1", or "2" and "2", or "2" and something completely different depending on which compiler and settings are used.
ya it will work sometimes but one cannot be sure that it works ...It sometimes not only causes
bus error but even can cause the whole program crash ...
i will give u an example
take a look at this ..
http://www.functionx.com/cpp/examples/returnreference.htm
here he is trying to return the reference of a variable which goes out of scope ...(Big blunder) ..but it works ....
u cant guarantee ..So its better (not better best ) never to return reference to data that goes out of scope