Pointer Increment in C - 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.

Related

How does the int *ptr= 5; is different than that of int *ptr= address of variable?

Though it is very basic and might seem silly, I am trying to understand what is difference between the int *ptr = 45 or 0xc8750; (some number) vs. int *ptr= &a; (address of variable).
What I already know is:
Pointers are made to store address of variables and to modify contents of pointed variables ( but I want to know how it will be achieved)
In latter case, I can assign *ptr to different address that is legal.
But, in first case it is illegal!.
Why the latter is illegal if both address/number are integers?
How differently will they be treated while storing in memory?
I have two piece of code/programs basically to highlight the same:
case-1:
#include <stdio.h>
int main()
{
int *ptr = 0xc42; // is this stored in read only memory?!! which later leads to seg faults in further assignments?!
*ptr = 45; //illegal leads seg fault.
return 0;
}
case-2:
int main()
{
int a=10, b=20;
int *ptr = &a; // is here get any special treatment and object will be created for *ptr!!!
*ptr = &b; //legal
printf(" *ptr = %d \n", *ptr);
*ptr = 20; //legal !!
printf(" *ptr = %d \n", *ptr);
*ptr = 50; //legal
printf(" *ptr = %d \n", *ptr);
return 0;
}
As we can see the *ptr = 20 and *ptr = 50 are legal and fine! (No segmentation faults).
Why is this assignment of int *ptr = 0xc989 or 5 different from int *ptr = &variable?.
Let's start from basics: a pointer is a variable containing the address pointing to data of a given type. If we declare
datatype* foo;
foo (that is currently not initialized) will contain the address of a variable of type datatype, and deferencing it
*foo = ...;
we are accessing that address and storing there its value.
In both cases we have * foo, but they're not the same!
In the first case the asterisk refers to datatype. The variable type is datatype *; the variable name is foo. foo contains an address.
In the second case we are dereferencing the address, in order to access it. The asterisk refers to the variable in order to perform the pointer dereferentiation.
So, when you write
int *ptr = 0xc42; // is this stored in read only memory?!!
// which later leads to seg faults in further assignments?!
*ptr = 45; //illegal leads seg fault.
With int *ptr = 0xc42; you are saying to the compiler that you are declaring a variable named ptr, of type int * and whose first value is 0xC42. (Note: as correctly stated by user Lundin, this assignment requires a further cast in order to be valid C).
With *ptr = 45; you are accessing the address pointed by ptr and assigning value 45. Is it legal? Well, it is if you previously assigned a valid address (and generally speaking it is if you assign to a pointer another variable's address with & operator, e.g int *ptr = &a;). But if you assign a random integer to it... it will likely lead to a segmentation fault.
Logically, if you are sure that the location, 0xc989, preserves what you need, int *ptr = 0xc989 perfectly valid (with regard to your thinking concept, as said by Roberto Caboni).
Technically, as said by Lundin, you need to cast it according to C standards.
First of all int *ptr = 0xc42; is not valid C and will not compile cleanly on a compiler configured to strict standard C. With gcc, clang and icc this means compiling with -std=c11 -pedantic-errors. For details, see "Pointer from integer/integer from pointer without a cast" issues.
int *ptr = (int*)0xc42; is valid C but fishy. To clarify, this stores an address inside the pointer variable itself, it doesn't store a value. So if you know that there is an int-sized item at memory address 0xc42, such as a memory-mapped hardware register, then you can point directly do it. But when doing so, it will only be meaningful to do that using volatile: volatile int *ptr = (volatile int*)0xc42;. Code like that mostly makes sense in embedded systems and other hardware-related programming.
As for why your second example works fine, the addresses there are assigned by the linker and not by the programmer, so they will point at valid, allocated data.

Confusing on pointer array

The following is the C code:
char *ptr[100];
printf("%s\n",*ptr++);
My question is: we know that array name is not a variable (Ritchie's book "The C programming language" Page 99), so if we define
int *pa,a[5];
This is legal:
pa = a; pa++;
while this is illegal:
a++;
Here char *ptr[100] defines a char pointer array, so ptr represents the initial address of the array. For the above code, if *ptr++ means *(ptr++), this is illegal because array name cannot be used as a variable, and also it's meaningless because *(ptr++) still gets an address as opposed to %s. However, if *ptr++ means (*ptr)++, it also looks strange... Can anyone help to understand this?
The above is my thinking process, my question is: how can *ptr++ give us a string as the code printf("%s\n",*ptr++); says?
Postfix increment ++ has a higher precedence than dereference *.
Thus, *ptr++ is interpreted as *(ptr++). And as you've correctly figured out, ptr++ isn't allowed if ptr is an array (of anything, values or pointers).
If ptr is a pointer, then *ptr++ will indeed increment the pointer (so it will point to the next value after the operation), and this expression will return the current pointed-to value (before increment of the pointer). This expression is indeed sometimes used, e.g. for copying memory areas, e.g.:
while (...) {
*dest++ = *src++; // Copy the current element, then increment both pointers
}
*ptr++ doesn't necessarily give you a string — it gives you a string if and only if ptr is pointing to a string. And in this case, it's not necessary to post-increment just to get the string — *ptr would be enough. ++ is done for another purpose.
For example, it ptr is a pointer to an "array" of strings (i.e. a pointer to a pointer to achar, i.e. char **ptr), then you could print all the strings like this:
int i;
for (i = 0; i < N; ++i) {
printf("%s\n",*ptr++); // '++' "jumps" to the next string
}
I believe this link should help you.
C/C++ int[] vs int* (pointers vs. array notation). What is the difference?
The array notation has a bounds limit while the pointer notation does not.
If you wanted to access the next in the array with array notation it would look something like a[n++] n being whatever the current index of the array you are at. Where as assigning ptr to a sets ptr to the first index of the array and you can increment a pointer.
*ptr++ is parsed as *(ptr++) - apply the ++ operator to ptr, then dereference the result.
As written, this results in a constraint violation - ptr is an array of pointers to char, and an expression of array type is a non-modifiable lvalue, and as such may not be the target of an assignment or the operand of the ++ and -- operators.
The line
printf("%s\n",*ptr++);
should (indeed, must) result in the compiler issuing a diagnostic on the order of "invalid lvalue in increment" or something along those lines.
No. 1:
void main(void)
{
int i;
char *ptr[3]={"how","are","you"};
for (i=0;i<3;i++)
printf("%s\n",ptr[i]);
}
This prints out correct answer. Good!
No.2:
void main(void)
{
int i;
char *ptr[3];
*ptr[0] = "how";
*ptr[1] = "are";
*ptr[2] = "you";
for (i=0;i<3;i++)
printf("%s\n",ptr[i]);
}
warning: assignment makes integer from pointer without a cast [enabled by default].....Why can't initialize like this?
No.3:
void main(void)
{
int i;
char *ptr[3]={"how","are","you"};
printf("%s\n",*ptr++);
}
error: lvalue required as increment operand....Why can't we use *ptr++?

Printing Pointer Data with Printf in C

My understanding is that when you declare a pointer, say int *a = 5, a is the pointer, and *ais the int pointed to - so the * indicates you're accessing the pointer data. (And the & is accessing the address). Hopefully this is correct?
How come when I'm doing printf it doesn't seem to work the way I want?
int main()
{
int *a = 5;
printf("%d\n",a);
return 0;
}
This gives me the correct result, which I didn't expect. When I did *a instead of a in the printf, it failed, which I'm confused with?
Nopes, int *a = 5; does not store an int value of 5 into the memory location pointed by a, the memory location itself is 5 (which is mostly invalid). This is an initialization statement, which initializes the variable a which is of type int * (a pointer) to 5.
For ease of understanding, consider the following valid case
int var = 10;
int *ptrVar = &var;
here, ptrVar is assigned the value of &var, the pointer. So, in other words, ptrVar points to a memory location which holds an int and upon dereferencing ptrVar, we'll get that int value.
That said, in general,
printf("%d\n",a);
is an invite to undefined behavior, as you're passing a pointer type as the argument to %d format specifier.
The declaration int *a does declare a to be a pointer. Thus, the declaration
int *a = 5;
initializes a with the value 5. Just like how
int i = 5;
would initialize i with the value 5.
There are very few situations where you would want to initialize a pointer variable with a literal value (other than 0 or NULL). Those would likely be embedded (or otherwise esoteric) applications where certain addresses have a defined meaning on a particular platform.

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

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.

Why is setting a derefernce pointer equal to a primitive illegal?

Why does setting the value of a dereferenced pointer raise a Segmentation fault 11? To make what I mean clear look a the follow code:
#include <stdio.h>
int *ptr;
*ptr = 2;
int main(){
printf("%d\n", *ptr);
return 0;
}
I thought that *ptr=2 would set the rvalue that the pointer ptr is point to to 2. Is that not the case? I apologize if for those c expert programmers, this is really easy/obvious.
Are we only allowed to set a dereferenced pointer (i.e. *ptr) to a value if that value had a memory address? i.e. like doing:
int k = 7;
int *ptr = k;
and then:
*ptr = 2;
The problem here is that ptr is not pointing to allocated space. See the following:
#include <stdio.h>
#include <stdlib.h>
int main(void){
// Create a pointer to an integer.
// This pointer will point to some random (likely unallocated) memory address.
// Trying set the value at this memory address will almost certainly cause a segfault.
int *ptr;
// Create a new integer on the heap, and assign its address to ptr.
// Don't forget to call free() on it later!
ptr = malloc(sizeof(*ptr));
// Alternatively, we could create a new integer on the stack, and have
// ptr point to this.
int value;
ptr = &value;
// Set the value of our new integer to 2.
*ptr = 2;
// Print out the value at our now properly set integer.
printf("%d\n", *ptr);
return 0;
}
It's not 'illegal', it's simply implementation defined. In fact, on some platforms (such as DOS), specific memory addresses were necessary, for example to write text to the video buffer which started at 0xB8000, or memory mapped controller I/O on the SNES.
On most current OS's, a feature called ASLR is used, for security reasons, which makes ancient modes of dedicated addresses a thing of the past, in favor of going through driver and kernel layers, which is what makes it 'illegal' for most places you would run it.
The most basic issue here is that you are not assigning ptr to a valid memory address, there are some cases where 0 is a valid memory address but usually not. Since ptr is global variable in your first case, it will be initialized to 0. remyabal asked a great follow-up question and best answer made me realize that this is a redeclaration here:
*ptr = 2;
and you are then setting ptr to have a value of 2 which is except by chance unlikely to point to a valid memory address.
If ptr was a local or automatic variable then it would be uninitialized and it's value would be indeterminate. Using a pointer with an indeterminate value is undefined behavior in both C and C++. It is in most case undefined behavior to use a NULL pointer as well although implementations are allowed to define the behavior.
On most modern system attempting to access memory your process does not own will result in a segmentation fault.
You can assign a valid memory address to ptr in a few ways, for example:
int k = 7;
int *ptr = &k;
^
note the use of of & to take the address of k or you could use malloc to allocate memory dynamically for it.
Your code is invalid, though some C compilers may permit it for compatibility with older versions of the language.
Statements, including assignment statements, are illegal (a syntax error) if they appear outside the body of a function.
You have:
int *ptr;
*ptr = 2;
at file scope. The first line is a valid declaration of an int* object called ptr, implicitly initialized to a null pointer value. The second line looks like an assignment statement, but since it's outside a function, the compiler most likely won't even try to interpret it that way. gcc treats it as a declaration. Old versions of C permitted you to omit the type name in a declaration; C99 dropped the "implicit int" rule. So gcc treats
*ptr = 2;
as equivalent to
int *ptr = 2;
and produces the following warnings:
c.c:4:1: warning: data definition has no type or storage class [enabled by default]
c.c:4:8: warning: initialization makes pointer from integer without a cast [enabled by default]
The first warning is because you omitted the int (or other type name) from the declaration. The second is because 2 is a value of type int, and you're using it to initialize an object of type int*; there is no implicit conversion from int to int* (other than the special case of a null pointer constant).
Once you get past that, you have two declarations of the same object -- but they're compatible, so that's permitted. And the pointer variable is initialized to (int*)2, which is a garbage pointer value (there's not likely to be anything useful at memory address 0x00000002).
In your main function, you do:
printf("%d\n", *ptr);
which attempts to print the value of an int object at that memory address. Since that address is not likely to be one that your program has permission to access, a segmentation fault is not a surprising result. (More generally, the behavior is undefined.)
(This is a fairly common problem in C: minor errors in a program can result in something that still compiles, but is completely different from what you intended. The way I think of it is that C's grammar is relatively"dense"; small random tweaks to a valid program often produce different but syntactically valid programs rather than creating syntax errors.)
So that's what your program actually does; I'm sure it's not what you intended it to do.
Take a deep breath and read on.
Here's something that's probably closer to what you intended:
#include <stdio.h>
int *ptr;
int main(void) {
*ptr = 2;
printf("%d\n", *ptr);
return 0;
}
Since there's now no initializer for ptr, it's implicitly initialized to a null pointer value. (And if ptr were defined inside main, its initial value would be garbage.) The assignment statement attempts to dereference that null pointer, causing a segmentation fault (again, the behavior is undefined; a segmentation fault is a likely result). Execution never reaches the printf call.
I thought that *ptr=2 would set the rvalue that the pointer ptr is point to to 2. Is that not the case?
Not quite. Pointers don't point to rvalues; an "rvalue" is merely the value of an expression. Pointers point to objects (if they point to anything). The assignment
*ptr = 2;
would assign the value 2 to the object that ptr points to -- but ptr doesn't point to an object!
Now let's see a version of your program that actually works:
#include <stdio.h>
int *ptr;
int variable;
int main(void) {
ptr = &variable;
*ptr = 2;
printf("*ptr = %d\n", *ptr);
printf("variable = %d\n", variable);
return 0;
}
Now ptr points to an object, and *ptr = 2 assigns a value to that object. The output is:
*ptr = 2
variable = 2

Resources