testing for valid pointer in c++ - c++

I wrote a little test to check for null pointer, I simplified it with int and 0, 1, instead of real classes, what I'm trying to test is something like this: return p ? 1 : 0;
which in real world would be return p ? p->callmethod() : 0;
bool TestTrueFalse();
void main()
{
int i = TestTrueFalse();
}
bool TestTrueFalse()
{
int one = 1;
int * p =&one;
*p = 0;
return p ? 1 : 0;
}
now, you can see, that once the pointer becomes 0 again, the test fails, why?
what's wrong with this? what's the solution?

*p = 0;
you probably meant
p = 0;
*p = 0 sets what the pointer points to, not the pointer

When testing a pointer value with a conditional in C++, it will return true if the value is non-zero and false if the value is 0. In your sample p is slated to point at the local one and hence has a non-zero address (even though the value at the address is 0). Hence you get true

A null pointer is a pointer which points to the address 0, not the value 0.
To set a pointer to null, do:
p = 0;
To elaborate, your code sets the pointed-to-int to 0. For example:
int i = 1;
int *p = &i;
assert(*p == 1); //p points to 1
*p = 0;
assert(*p == 0 && i == 0); //p points to the same location, but that location now contains 0

The code *p = 0; does not set the pointer to null. It sets what p is pointing to zero.

A pointer is an address in memory. int *p = &one; takes the address of the variable one, and stores it in p. *p = 0; stores 0 in the memory pointed to by p, meaning that the value of one is now 0. So, you have changed what p points to, but not p itself. TestTrueFalse() will return 1.

to test it for a null pointer before inspecting the value pointed to you might use code like
if(ip != NULL)
taken from http://www.eskimo.com/~scs/cclass/notes/sx10d.html
NULL might be safer in your code, as it is more compiler independent than just writing 0. and it might also be more clear for others to read in your code.

Related

C++ pointer and increment operator (++)

Recently, I begin to learn C++ language for Pointer series, I knew the pointer is the specific var what is used to hold the address of another variable. And when we change the value at the memory area which the pointer is hold, it also change the value of that var. So then i just wrote the code to do it.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main(int argc, char const *argv[])
{
int n=5;
int *p=&n; //pointer p hold the address of n
std::cout<<"value of n = "<<n<<endl;
std::cout<<"value of n = "<<*p<<endl;
std::cout<<"value of n= "<<*(&n)<<endl;
std::cout<<"the address of n = "<<&n<<endl;
std::cout<<"the address of n = "<<p<<endl;
*p=19; //change the value at the address of n -> mean n definitely change
std::cout<<"value of n once *p changed = "<<n<<endl;
p++; //p address increase 4 bytes
std::cout<<"address of p changed = "<<p<<endl;
(*p)++;
std::cout<<"address of p = "<<p<<endl;
return 0;
}
then i got the resul below :
As I mark red in my picture, when I do (*p)++ - I understood that the value at the address p hold will increase 1, but once I check the result, it didn't show the value of p after (*p)++ line , just the address of p has increased 1 byte.
What is the reason for this?
If we break down your code into the important parts, we see:
int n=5; // 1.
int *p = &n; // 2.
p++; // 3.
(*p)++; // 4. Dereference and increment.
You clearly have a good grip on what 1-3 do in this code. But, 4 is a big problem. In 3, you changed the pointer. The pointer previously pointed to n, after incrementing, what does it point to now?Wherever it is, it is not necessarily memory that we own and can actively change.
In line 4, you change it. This is undefined behaviour which, from the linked page you can see:
undefined behavior - there are no restrictions on the behavior of the program.
So the program can do pretty much anything.
Your program has undefined behavior.
Let's look at this sequence picked from your program:
int n=5;
int *p=&n;
p++; // p now points to some unknown memory area
(*p)++; // here you dereference `p` - undefined behavior.
You are never allowed to dereference a pointer that is not pointing to an object that is "alive".

How does the '--p' work in for(p=&(*L).elem[(*L).length-1];p>=q;--p)?

I am trying to debug the following code:
Status ListInsert_Sq(SqLIst *L, int i, LElemType_Sq e)
{
LElemType_Sq *newbase;
LElemType_Sq *p, *q;
if(i<1 || i>(*L).length+1)
return ERROR;
if((*L).length >= (*L).listsize)
{
newbase = (LElemType_Sq*)realloc(LElemType_Sq *)realloc((*L).elem, ((*L).listsiz+LISTINCREMENT)*sizeof(LElemType_Sq));
if(!newbase)
exit(OVERFLOW);
(*L).elem = newbase;
(*L).listsize += LISTINCREMENT;
}
q = &(*L).elem[i-1];
for(p=&(*L).elem[(*L).length-1];p>=q;--p)
*(p+1) = *p;
*q = e;
(*L).length++;
return OK;
}
Is using --p correct here?
Specifically I wonder if the last element of the list is going to be moved or overwritten by the previous element?
Thank you!
After rewriting,the guessed intention of the code looks like:
#include <stdlib.h>
#include <string.h>
#include "listmeuk.h"
Status ListInsert_Sq(SqLIst *lp, int index, LElemType_Sq elem)
{
if(index<1 || index>lp->length+1) return ERROR; // this assumes 1-based indexing
index--; // transform to zero-based indexing
if(lp->length >= lp->listsize)
{
LElemType_Sq *newbase;
newbase = realloc(lp->elem, (lp->listsiz+LISTINCREMENT) *sizeof *newbase);
if(!newbase) exit(OVERFLOW);
lp->elem = newbase;
lp->listsize += LISTINCREMENT;
}
if(index < lp->length) memmove(&(lp->elem[index+1]), &(lp->elem[index]), (lp->length-index) * sizeof lp->elem[0] );
lp->elem[index] = elem;
lp->length++;
return OK;
}
This code (in which I have added the missing semicolon):
for(p=&(*L).elem[(*L).length-1];p>=q;--p)
*(p+1) = *p;
sets p to point to the last assigned element in the array elem. Then *(p+1) = *p; copies this last set element to the newly allocated space (allocated with realloc) above. (By “assigned element”, I mean one for which a value had been assigned.)
Then --p decrements the pointer to point to the previous element. (Using arithmetic on pointers works in units of array elements.) Then *(p+1) = *p; copies the second-to-last assigned element to the previous space of the last assigned element. Then the loop continues on this way, effectively moving each element one further space up the array.
Ultimately, the loop appears to be intended to stop when the element with index i-1 has been moved, as q is set to the address of that element with q = &(*L).elem[i-1];.
However, it is defective. If i is one, then q points to the first element of the array, and p will eventually reach that element, and --p will attempt to decrement p to point before the start of the array. The behavior of this attempt is not defined by the C standard. (This presumes L points to the start of the array. It is possible L points into an array beyond its start, in which case this problem does not occur.)

Double pointer **src and operation (*(*src)++ = reg_offset)

I'm newer in C/C++, I really confuse about a function that executes complex operation. I just want to know how it works ? What does function mean ?
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data){
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
Any idea ??
Update my understanding:
void writetoXX(unsigned int **src, unsigned int reg_offset, unsigned int reg_data) {
*(*src)++ = reg_offset;
*(*src)++ = reg_data;
}
int main() {
int a[10] = { 0 };
int *p = a;
printf("Before !!\n");
for(int i=0;i<10;i++)
printf("%d ", a[i]);
writetoXX(&p, 20, 30);
printf("After !!! \n");
for (int i = 0; i<10; i++)
printf("%d ", a[i]);
getchar();
return 0;
}
After run this program, I see that the function writetoXX change value arr[0][0] and arr[0][1] to 20 and 30. It means that the function is used for write data to 2 consecutive blocks.
And output is below:
Before !!
0 0 0 0 0 0 0 0 0 0
After !!
20 30 0 0 0 0 0 0 0 0
src is a pointer to a pointer to an unsigned int, for example this is used for bidimensional arrays. Because of the operator precedence, the routine does:
take *src, it is a pointer to an unsigned int
(*src)++ increments the pointer, such that it points to the next unsigned int. It is a post increment, so it returns the value before the increment.
*(*src)++ is the unsigned int pointed by *src before the increment ++
So in summary, you take * src which is a pointer to unsigned int, you assign the first pointed data to reg_offset, then you increment such pointer, then you assign the next element to reg_data, and finally you increment again the pointer *src.
Double pointer is a variable which stores address of another pointer variable.
Consider this *(*src)++ = reg_offset;
In one line: The value of reg_offset is stored at current address stored in src and the address in src is incremented.
You can consider this happening in the following order.
1) As you know src is a variable which is storing address of another pointer or memory space.
2) So (*src) whill give address of the pointed variable or memory space.
3) Due to operator precedence, (*src)++ takes place. Which you can read like, after executing the current line, increment the address value stored in src.
4) Now *(*src) Which is the memory space with address stored in (*src). So *(*src) = reg_offset; will copy the value of reg_offset to that address. I have removed ++ in this line just for clarity.
5) When the second line *(*src)++ = reg_data; is about to be executed, the (*src) will be pointing to next address. So reg_data is written to next address.
Please note, next address does not mean current_address+1. It actually means current_address+sizeof(data type). Ifunsigned int is 4 byte in your compiler, then next_address = current_address+4
You can print content of (*src) in between the lines and verify.

Why post increment to value of a variable by pointer variable (*variablePointer++) returns garbage value?

I'm just playing around pre/post increment/decrement in C language. In the program below, everything works fine with variable var. But increments to the pointer variable *varAddress++ return garbage value.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int var = 1;
int *varAddress = &var;
printf("Value befor pre increment %d\n",*varAddress);
++*varAddress;
printf("Value after pre increment %d\n",*varAddress);
printf("Value befor post increment %d\n",*varAddress);
*varAddress++;
printf("Value after post increment %d\n",*varAddress);
return 0;
}
Output
Value befor pre increment 1
Value after pre increment 2
Value befor post increment 2
Value after post increment 1606416400
Program ended with exit code: 0
According to the Operator Precedence, suffix increment has higher precedence than indirection operator, so *varAddress++ is equivalent as:
*(varAddress++);
which will increase the pointer itself, then point to memory unallocated somewhere else, that's why *varAddress will return garbage value (this is UB).
You might want:
(*varAddress)++;
++ has higher precedence than * so by doing *varAddress++ you are moving a pointer to some un-owned location and trying to dereference it, which will lead to undefined behavior.
#include<stdio.h>
void main(){
char arr[] ="abcd";
char *p=arr,*q=arr;
char k,temp;
temp = *p++; /* here first it assigns value present in address which
is hold by p and then p points to next address.*/
k = ++*q;/*here increments the value present in address which is
hold by q and assigns to k and also stores the incremented value in the same
address location. that why *q will get 'h'.*/
printf("k is %c\n",k); //output: k is h
printf("temp is %c\n",temp);//output: temp is g
printf("*p is %c\n",*p);//output: *p is e
printf("*q is %c",*q);//output: *q is h
}

Casting pointer to Array (int* to int[2])

How do I cast or convert an int* into an int[x]?
First, I know that pointers can be indexed. So I know that I can loop through the pointer and array and manually convert the pointer. (eg. a for loop with arr[i] = p[i]). I want to know if the same result can be achieved in fewer lines of code.
As an example I tried to cast pointer int* c = new int[x] to an array int b[2]
int a = 1;
int b[2] = { 2, 3 };
int* c = new int[b[1]];
c[0] = b[0];
c[1] = b[1];
c[2] = a;
I wanted to see what values were where, so I made a simple program to output addresses and values. The output is just below:
Address of {type: int} &a = 0031FEF4; a = 1
Address of {type: int[2]} &b = 0031FEE4; b = 0031FEE4
Address of {type: int[2]} &b[0] = 0031FEE4; b[0] = 2
Address of {type: int[2]} &b[1] = 0031FEE8; b[1] = 3
Address of {type: int*} &c = 0031FED8; c = 008428C8
Address of {type: int*} &c[0] = 008428C8; c[0] = 2
Address of {type: int*} &c[2] = 008428D0; c[2] = 1
Once I made sure I knew what was where I tried a few things. The first idea that came to mind was to get the address of the second element to the pointer's allocation, then replace the array's memory address with it (see the code just below). Everything I did try ultimately failed, usually with syntax errors.
This is what I tried. I really want this to work, since it would be the simplest solution.
b = &c[1];
This did not work obviously.
Edit: Solution:
Don't do it!
If it's necessary create a pointer to an array and then point to the array; this is pointless for any purposes I can fathom.
For more detailed information see the answer by rodrigo below.
First of all b is an array, not a pointer, so it is not assignable.
Also, you cannot cast anything to an array type. You can, however, cast to pointer-to-array.
Note that in C and C++ pointer-to-arrays are rather uncommon. It is almost always better to use plain pointers, or pointer-to-pointers and avoid pointer-to-arrays.
Anyway, what you ask can be done, more or less:
int (*c)[2] = (int(*)[2])new int[2];
But a typedef will make it easier:
typedef int ai[2];
ai *c = (ai*)new int[2];
And to be safe, the delete should be done using the original type:
delete [](int*)c;
Which is nice if you do it just for fun. For real life, it is usually better to use std::vector.
Though you can't reassign an array identifier.. sometimes the spirit of what you're doing allows you to simply create a reference and masquerade yourself as an array. Note: this is just a slight extension of rodrigo's answer... and it is still worth mentioning that there is probably a better way to accomplish whatever the task is.
#include <iostream>
int main() {
int x[1000] = {0};
for(int i = 0; i < 10; ++i) {
int (&sub_x)[100] = *(int(*)[100])(&x[i*100]);
//going right to left basically:
// 1. x[i*100] -- we take an element of x
// 2. &x[N] -- we take the address
// 3. (int(*)[100]) -- we cast it to a pointer to int[100]
// 4. *(...) -- lastly we dereference the pointer to get an lvalue
// 5. int (&sub_x)[100] -- we create the reference `sub_x` of type int[100]
for(int j = 0; j < 100; ++j) {
sub_x[j] = (i*100)+j;
}
}
for(int i = 0; i < 1000; ++i) {
if(i != 0) {
std::cout << ", ";
}
std::cout << x[i];
}
std::cout << std::endl;
}
As you'd expect the output just ends up printing 0-999 with no gaps
output:
0, 1, 2, ..., 999