Pointer arithmetic and malloc()/calloc() functions [duplicate] - c

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
There're 2 things I don't understand, usually when using malloc() / calloc() we type cast the it because they return a void pointer so we type cast it to our pointer type so we could do pointer arithmetic with it.
So I've made a code example where I use malloc() and I don't type cast it and the pointer arithmetic still works :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = malloc(8);
*p++ = 30;
*p = 40;
printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
return 0;
}
why is that ?
Another question of mine regarding to pointers arithmetic is that the code I showed you above, I originally wrote it as follow :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p = malloc(8);
*p++ = 30;
*p-- = 40;
printf("p points to address [%p] which holds a value of %d, p points to address [%p] which holds a value of %d\n", p, *p++, p, *p--);
return 0;
}
Notice the difference is *p-- = 40.
I've use p-- because I wanted to print the correct address the pointer was pointing at, I was assuming that after I use p++ I need to use p-- so the pointer will point at the address of the value of 30, but if I added the p-- and printed it I've noticed that it prints another value.
So something here doesn't click for me what's going on with it ? Also if I removed the -- and then printed, it printed 30 and then 40 as I expected BUT the address remained the same, I've expected it to be the previous address+4 which it wasn't yet the value changed, what's going on ?
http://imgur.com/GRRInBL

Pointer arithmetic depends on the type with which your pointer is declared. Since your pointer is int *, then ++ and -- will increment and decrement the (raw) value of the pointer by sizeof(int) so that you can access adjacent int values.
In C, it is possible to assign a void * to another type of pointer (such as int *) without triggering a warning (this is not true in C++). In this case the cast is implicitly performed by the compiler.

Related

Difference between returning address and returning pointer

#include <stdio.h>
#include <conio.h>
void main()
{
int m = 20;
int n = 30;
int *x = (int *)m;
int *y = (int *)n;
printf("%d", y-x); //Output is 5
}
How is the output 5? One of the reason could be that x and y consider 20 and 30 as address and during pointer arithmetic the value could be (30-20)/(size of int) which is 10/2 = 5.
My doubt is what is the difference between returning pointer and returning address ? Why the address of m was not stored in pointer variable x?
The behaviour of your program is undefined.
Pointer arithmetic - including the difference between two pointers - is only valid within arrays (including one past the end of the arrray), or between the address of a scalar and one past that.
The behaviour of your casts from an int to a pointer to an int is also undefined.
If you do have a valid difference between two pointers, then use the format specifier %td to output it.
The address of m wasn't stored in x because you didn't assign it the address of m. You assigned it the value of m. The cast you applied masked the fact that you attempted to assign an integer to a pointer, which the compiler would have warned you about.
If you want to use the address of a variable, use the address-of operator &:
int *x=&m;
int *y=&n;
You are correct regarding why the output is 5. The values of m and n are assigned to pointers and are thus treated as addresses.
Note however that pointer subtraction is undefined unless both operands point to members of the same array (or one past the end of that array). Also note that it is undefined behavior to print pointers with the %d format specifier. You need to use %p instead, and you need to cast the given parameter to void * (one of the rare cases where a cast to/from void * is required).
if you want to store the adress of m in x simply do int* x = &m;
the casting to int type pointer here is causing the problem in my optinion.
also if you want to calculate the values of y-x then do *y-*x. as it is in your code you calculate the adress of n - the adress of m.
You have to use %p if you would like to show the address that is stored in a pointer. In your code, you should use * before the name of the pointer.
#include<stdio.h>
int main()
{
int m=20; int n=30;
int *x= &m;
int *y= &n;
printf("\n%d", (*y)-(*x)); //Output is 10
printf("\n%p address of m", x);
printf("\n%p address of n", y);
return 0;
}
int *x=(int *)m;
int *y=(int *)n;
By doing this what you would be doing is -
in a pointer x - you put the value m ( Treat this as a pointer as well as you are doing int *.
Hence x would have a value of 20 ( 0x14 ) and y would have a value of 30 ( 0x1E).
Pointer arithmetic is bit different from normal arithmetic operation
https://www.tutorialspoint.com/cprogramming/c_pointer_arithmetic.htm
And about assigning address you should use a &variable to do that

Printing pointer raises a runtime error [duplicate]

This question already has answers here:
What exactly is meant by "de-referencing a NULL pointer"?
(8 answers)
Closed 5 years ago.
I am studying C at school , and I am facing a problem with pointers , Why does this unhandled error rise (im using visual studio 2013 express for desktop on 64 bit windows 10) , when I try to run the code below.
My question is , Why is this happening?
Code Block :
// ~~ Libraries Or Header Files. ~~ //
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ~~ Main Function ~~ //
int main(void)
{
// ~ Variables ~ //
int * p = NULL;//#define NULL ((void *)0)
printf(*p);
//printf(p)l also raises an error.
// ~ END ~ //
system("PAUSE");
return 0;
}
Error:
" Unhandled exception at 0x009A3C2A in hwQ3.exe: 0xC0000005: Access violation
reading location 0x00000000 ".
There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string). Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...
You've initialized p to NULL. NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value). When you write *p, you're saying, "I want the value of the integer object p points to." Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
Using the unary & operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
p = &x; // x is an integer object
p = &a[i]; // a is an array of integer, so a[i] is an integer object
p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
etc.
Calling one of malloc, calloc, or realloc:
p = malloc( sizeof *p );
Using an array expression in most circumstances. Unless it is the operand of the sizeof or unary & operators, or is a string literal being used to intialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. In the case of printf, when we write
printf( "this is a test\n" );
the type of the string literal "this is a test\n" is converted from type "16-element array of char" to "pointer to char", and its value is the address of the first character in the string - that address value is what actually gets passed to printf.
The first argument to printf(...) is a const char *format so in both cases you're trying to dereference a NULL pointer. That causes you to access memory outside your allowable range (at zero).
Basic information about pointers:
Pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this:
int *ip;
Pointers are generated with the address-of'' operator &, which we can also think of as thepointer-to'' operator. Demonstrating this by declaring (and initializing) an int variable i, and then setting ip to point to it:
int i = 5;
ip = &i;
Example pointer usage:
#include <stdio.h>
int main(){
int var =10;
int *ptr = &var;
printf("%d\n", *ptr);
return 0;
}
What happens when you deference the pointer to NULL?
int *a = NULL; // a is a null pointer
int b = *a; // CRASH: dereferencing a, trying to read it
*a = 0; // CRASH: dereferencing b, trying to write it

Printing character pointer in C

I was learning pointers in C when I wrote the following code:
#include <stdio.h>
main()
{
char *p = 0;
*p = 'a';
printf("value in pointer p is %c\n", *p);
}
When I compiled the code, It was compiled successfully. Although, when I executed its out file, a runt-time error occurred: Segmentation Fault (core dumped)
I couldn't understand why that run-time error occurred. After all, the pointer p was pointing to character a, and thus the output should've been a.
Although, when I wrote the following code, it compiled and ran successfully:
#include <stdio.h>
main ()
{
char *p = 0;
char output = 'a';
p = &output;
printf("value which pointer p points is %c\n", *p);
}
Can someone explain me why the first program fails, while the second program runs successfully?
Your code invokes undefined behavior because you are dereferencing a NULL1 pointer. A pointer needs to point to valid memory, a simple way to achieve what you want is this
#include <stdio.h>
int // `main()' MUST return `int'
main(void)
{
char *pointer;
char value;
pointer = &value; // Now the pointer points to valid memory
*pointer = 'a';
printf("value in pointer p is %c\n", *pointer);
return 0;
}
1
6.3.2.3 Pointers
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. 66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
66)The macro NULL is defined in (and other headers) as a null pointer constant; see 7.19.
6.5.3.2 Address and indirection operators
Semantics
The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.102)
102)Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.
In the first example, you set p to 0, which on most implementations is the same as NULL. You then attempt to dereference that pointer (read/write the memory location that p points to), which leads to the core dump. p is not pointing to the character a. This *p = 'a' says "take the memory location that p points to and put a there".
In the second example, you're setting p to the address of output, so it points to a known memory location. Then when you dereference is, you're reading the value at the location where p points, i.e. output. This is valid usage.
A pointer is a "special" variables that store the address of another variables. Take a look at this program, I hope that it will help you clarifying what a pointer is and how to use it :
#include <stdio.h>
int main(void){
int x = 10, *pointer = 0;
pointer = &x;
printf("\nThe address of x : %p.\n", &x);
printf("\nThe address of the pointer : %p.\n", pointer);
printf("\nThe value of x : %d.\n", x);
*pointer += 10;
printf("\nThe value of x after we modifed it with the pointer : %d.\n\n", x);
return 0;
}
If you compile and give this program a run, this will be its output:
The address of x : 0xbf912108.
The address of the pointer : 0xbf912108.
The value of x : 10.
The value of x after we modifed it with the pointer : 20.
As you can clearly see the address of the pointer is the same of the variable itself. That's why when you modify a pointer (for example in my program I do *pointer += 10) it's actually modifying the variable.

Pointer Increment in C

I am getting an odd error in a small C program in which I'm trying to learn how to use pointers.
I assumed everything was working because it compiled but when I try to run the code, it says C program has stopped responding. I must be doing something incorrect... Any help?
#include <stdio.h>
int main()
{
int k = 22;
int z = 11;
int *ptr = k;
printf("%d \n",*ptr);
ptr++;
printf("%d \n",*ptr);
getchar();
return 0;
}
You need to assign address of k not it's value..
int *ptr = &k;
Also after ptr++; *ptr would print garbage value(though behavior is undefined)
It is very simple to understand pointer, the pointer is a value to store an memory address, and you must always ensure the memory address is avaiable!
so here is the 1st error;
int *ptr = k;
so 1st you shall assign an valid memory address to the ptr before you use it, correct one shall be
int *ptr;
ptr = &K
star (*) is use to get the value which is stored in the memory address you assigned. so to increase the value , you shall
(*ptr)++
instead of
ptr++
this will increase the address instead of value itself, and you r really unknown what is stored there.
Your problem is here:
int *ptr = k;
you are assigning the value of k to ptr not the address of, so you are missing the address operator(&):
int *ptr = &k;
^
gcc by default gives the following warning:
warning: initialization makes pointer from integer without a cast [enabled by default]
So if you are not seeing a waring then you should enable warnings.
Performing indirection on ptr after you increment here:
ptr++;
printf("%d \n",*ptr);
^
indirection
it is undefined behavior in this case since it will be pointing to one past the last element, since pointers to non-arrays are treated as 1 element arrays for this case as per C99 section 6.5.6 Additive operators paragraph 7.

Some pointer questions [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is array name a pointer in C?
I was running the following code
#include <stdio.h>
int main()
{
int a[4] = {1,2,3,4};
int (*b)[4] = &a;
int k = sizeof(a);
printf("\n\n%d\n\n", k);
printf("a = %u, b = %u, *b = %u, data = %d", a, b, *b, **b);
return 0;
}
I got the following output
a = 3485401628, b = 3485401628, *b = 3485401628, data = 1
Here I am assigning the address of a to b, as the type of b is int**, but in the output I am getting that the address pointed by the a is the same as the address pointed by b.
It seems little confusing to me. What is the explanation?
The value of array a is the pointer to the first element of the array a.
The value of pointer &a (which is the same value and type as pointer b) is the pointer to the array a.
They have the same value (but different types) as they both start at the same memory address. There is no padding possible at the beginning of an array.
When evaluated a is of type int * and &a is of type int (*)[4].
Note that the correct way to print the address of a pointer is to use conversion specifier p. E.g.,
/* And p requires the argument to be a void *, so use a cast if
* it is not the case
*/
printf("%p %p\n", (void *) a, (void *) &a);
On expressions (such as an argument for printf) arrays are decayed to pointers (to their respective arrays), meaning that if "b" points to "a", on an expression, "a" will also be a pointer to "a" (the block of memory allocated for "a").
The way of accessing elements at runtime however (internally), is different. In this case, "b" would require an additional indirection.

Resources